| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 1 | package com.mirantis.mk | 
| Jakub Josef | 6d8082b | 2017-08-09 12:40:50 +0200 | [diff] [blame] | 2 |  | 
| Jakub Josef | b41c8d5 | 2017-03-24 13:52:24 +0100 | [diff] [blame] | 3 | import static groovy.json.JsonOutput.prettyPrint | 
 | 4 | import static groovy.json.JsonOutput.toJson | 
| Jakub Josef | 6d8082b | 2017-08-09 12:40:50 +0200 | [diff] [blame] | 5 |  | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 6 | import com.cloudbees.groovy.cps.NonCPS | 
| Jakub Josef | b7ab847 | 2017-04-05 14:56:53 +0200 | [diff] [blame] | 7 | import groovy.json.JsonSlurperClassic | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 8 | /** | 
 | 9 |  * | 
 | 10 |  * Common functions | 
 | 11 |  * | 
 | 12 |  */ | 
 | 13 |  | 
 | 14 | /** | 
 | 15 |  * Generate current timestamp | 
 | 16 |  * | 
 | 17 |  * @param format    Defaults to yyyyMMddHHmmss | 
 | 18 |  */ | 
 | 19 | def getDatetime(format="yyyyMMddHHmmss") { | 
 | 20 |     def now = new Date(); | 
 | 21 |     return now.format(format, TimeZone.getTimeZone('UTC')); | 
 | 22 | } | 
 | 23 |  | 
 | 24 | /** | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 25 |  * Return workspace. | 
 | 26 |  * Currently implemented by calling pwd so it won't return relevant result in | 
 | 27 |  * dir context | 
 | 28 |  */ | 
 | 29 | def getWorkspace() { | 
 | 30 |     def workspace = sh script: 'pwd', returnStdout: true | 
 | 31 |     workspace = workspace.trim() | 
 | 32 |     return workspace | 
 | 33 | } | 
 | 34 |  | 
 | 35 | /** | 
| Filip Pytloun | 81c864d | 2017-03-21 15:19:30 +0100 | [diff] [blame] | 36 |  * Get UID of jenkins user. | 
 | 37 |  * Must be run from context of node | 
 | 38 |  */ | 
 | 39 | def getJenkinsUid() { | 
 | 40 |     return sh ( | 
 | 41 |         script: 'id -u', | 
 | 42 |         returnStdout: true | 
 | 43 |     ).trim() | 
 | 44 | } | 
 | 45 |  | 
 | 46 | /** | 
 | 47 |  * Get GID of jenkins user. | 
 | 48 |  * Must be run from context of node | 
 | 49 |  */ | 
 | 50 | def getJenkinsGid() { | 
 | 51 |     return sh ( | 
 | 52 |         script: 'id -g', | 
 | 53 |         returnStdout: true | 
 | 54 |     ).trim() | 
 | 55 | } | 
 | 56 |  | 
 | 57 | /** | 
| Alexander Evseev | bc1fea4 | 2017-12-13 10:03:03 +0100 | [diff] [blame] | 58 |  * | 
 | 59 |  * Find credentials by ID | 
 | 60 |  * | 
 | 61 |  * @param credsId    Credentials ID | 
 | 62 |  * @param credsType  Credentials type (optional) | 
 | 63 |  * | 
 | 64 |  */ | 
 | 65 | def getCredentialsById(String credsId, String credsType = 'any') { | 
 | 66 |     def credClasses = [ // ordered by class name | 
 | 67 |         sshKey:     com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.class, | 
 | 68 |         cert:       com.cloudbees.plugins.credentials.common.CertificateCredentials.class, | 
 | 69 |         password:   com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials.class, | 
 | 70 |         any:        com.cloudbees.plugins.credentials.impl.BaseStandardCredentials.class, | 
 | 71 |         dockerCert: org.jenkinsci.plugins.docker.commons.credentials.DockerServerCredentials.class, | 
 | 72 |         file:       org.jenkinsci.plugins.plaincredentials.FileCredentials.class, | 
 | 73 |         string:     org.jenkinsci.plugins.plaincredentials.StringCredentials.class, | 
 | 74 |     ] | 
 | 75 |     return com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials( | 
 | 76 |         credClasses[credsType], | 
 | 77 |         jenkins.model.Jenkins.instance | 
 | 78 |     ).findAll {cred -> cred.id == credsId}[0] | 
 | 79 | } | 
 | 80 |  | 
 | 81 | /** | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 82 |  * Get credentials from store | 
 | 83 |  * | 
 | 84 |  * @param id    Credentials name | 
 | 85 |  */ | 
| Jakub Josef | 3d9d9ab | 2017-03-14 15:09:03 +0100 | [diff] [blame] | 86 | def getCredentials(id, cred_type = "username_password") { | 
| Alexander Evseev | bc1fea4 | 2017-12-13 10:03:03 +0100 | [diff] [blame] | 87 |     warningMsg('You are using obsolete function. Please switch to use `getCredentialsById()`') | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 88 |  | 
| Alexander Evseev | bc1fea4 | 2017-12-13 10:03:03 +0100 | [diff] [blame] | 89 |     type_map = [ | 
 | 90 |         username_password: 'password', | 
 | 91 |         key:               'sshKey', | 
 | 92 |     ] | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 93 |  | 
| Alexander Evseev | bc1fea4 | 2017-12-13 10:03:03 +0100 | [diff] [blame] | 94 |     return getCredentialsById(id, type_map[cred_type]) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 95 | } | 
 | 96 |  | 
 | 97 | /** | 
 | 98 |  * Abort build, wait for some time and ensure we will terminate | 
 | 99 |  */ | 
 | 100 | def abortBuild() { | 
 | 101 |     currentBuild.build().doStop() | 
 | 102 |     sleep(180) | 
 | 103 |     // just to be sure we will terminate | 
 | 104 |     throw new InterruptedException() | 
 | 105 | } | 
 | 106 |  | 
 | 107 | /** | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 108 |  * Print pretty-printed string representation of given item | 
 | 109 |  * @param item item to be pretty-printed (list, map, whatever) | 
 | 110 |  */ | 
 | 111 | def prettyPrint(item){ | 
 | 112 |     println prettify(item) | 
 | 113 | } | 
 | 114 |  | 
 | 115 | /** | 
| Jakub Josef | b41c8d5 | 2017-03-24 13:52:24 +0100 | [diff] [blame] | 116 |  * Return pretty-printed string representation of given item | 
 | 117 |  * @param item item to be pretty-printed (list, map, whatever) | 
 | 118 |  * @return pretty-printed string | 
 | 119 |  */ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 120 | def prettify(item){ | 
 | 121 |     return groovy.json.JsonOutput.prettyPrint(toJson(item)).replace('\\n', System.getProperty('line.separator')) | 
| Jakub Josef | b41c8d5 | 2017-03-24 13:52:24 +0100 | [diff] [blame] | 122 | } | 
 | 123 |  | 
 | 124 | /** | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 125 |  * Print informational message | 
 | 126 |  * | 
 | 127 |  * @param msg | 
 | 128 |  * @param color Colorful output or not | 
 | 129 |  */ | 
 | 130 | def infoMsg(msg, color = true) { | 
 | 131 |     printMsg(msg, "cyan") | 
 | 132 | } | 
 | 133 |  | 
 | 134 | /** | 
 | 135 |  * Print error message | 
 | 136 |  * | 
 | 137 |  * @param msg | 
 | 138 |  * @param color Colorful output or not | 
 | 139 |  */ | 
 | 140 | def errorMsg(msg, color = true) { | 
 | 141 |     printMsg(msg, "red") | 
 | 142 | } | 
 | 143 |  | 
 | 144 | /** | 
 | 145 |  * Print success message | 
 | 146 |  * | 
 | 147 |  * @param msg | 
 | 148 |  * @param color Colorful output or not | 
 | 149 |  */ | 
 | 150 | def successMsg(msg, color = true) { | 
 | 151 |     printMsg(msg, "green") | 
 | 152 | } | 
 | 153 |  | 
 | 154 | /** | 
 | 155 |  * Print warning message | 
 | 156 |  * | 
 | 157 |  * @param msg | 
 | 158 |  * @param color Colorful output or not | 
 | 159 |  */ | 
 | 160 | def warningMsg(msg, color = true) { | 
| Jakub Josef | 0e7bd63 | 2017-03-16 16:25:05 +0100 | [diff] [blame] | 161 |     printMsg(msg, "yellow") | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 162 | } | 
 | 163 |  | 
 | 164 | /** | 
| Jakub Josef | 952ae0b | 2017-03-14 19:04:21 +0100 | [diff] [blame] | 165 |  * Print debug message, this message will show only if DEBUG global variable is present | 
 | 166 |  * @param msg | 
 | 167 |  * @param color Colorful output or not | 
 | 168 |  */ | 
 | 169 | def debugMsg(msg, color = true){ | 
| Jakub Josef | 9a836ac | 2017-04-24 12:26:02 +0200 | [diff] [blame] | 170 |     // if debug property exists on env, debug is enabled | 
| Jakub Josef | 66976f6 | 2017-04-24 16:32:23 +0200 | [diff] [blame] | 171 |     if(env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true"){ | 
| Jakub Josef | 74b3469 | 2017-03-15 12:10:57 +0100 | [diff] [blame] | 172 |         printMsg("[DEBUG] ${msg}", "red") | 
| Jakub Josef | 952ae0b | 2017-03-14 19:04:21 +0100 | [diff] [blame] | 173 |     } | 
 | 174 | } | 
 | 175 |  | 
 | 176 | /** | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 177 |  * Print message | 
 | 178 |  * | 
 | 179 |  * @param msg        Message to be printed | 
 | 180 |  * @param level      Level of message (default INFO) | 
 | 181 |  * @param color      Color to use for output or false (default) | 
 | 182 |  */ | 
 | 183 | def printMsg(msg, color = false) { | 
 | 184 |     colors = [ | 
 | 185 |         'red'   : '\u001B[31m', | 
 | 186 |         'black' : '\u001B[30m', | 
 | 187 |         'green' : '\u001B[32m', | 
 | 188 |         'yellow': '\u001B[33m', | 
 | 189 |         'blue'  : '\u001B[34m', | 
 | 190 |         'purple': '\u001B[35m', | 
 | 191 |         'cyan'  : '\u001B[36m', | 
 | 192 |         'white' : '\u001B[37m', | 
 | 193 |         'reset' : '\u001B[0m' | 
 | 194 |     ] | 
 | 195 |     if (color != false) { | 
| Jakub Josef | e6c562e | 2017-08-09 14:41:03 +0200 | [diff] [blame] | 196 |         print "${colors[color]}${msg}${colors.reset}" | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 197 |     } else { | 
 | 198 |         print "[${level}] ${msg}" | 
 | 199 |     } | 
 | 200 | } | 
 | 201 |  | 
 | 202 | /** | 
 | 203 |  * Traverse directory structure and return list of files | 
 | 204 |  * | 
 | 205 |  * @param path Path to search | 
 | 206 |  * @param type Type of files to search (groovy.io.FileType.FILES) | 
 | 207 |  */ | 
 | 208 | @NonCPS | 
 | 209 | def getFiles(path, type=groovy.io.FileType.FILES) { | 
 | 210 |     files = [] | 
 | 211 |     new File(path).eachFile(type) { | 
 | 212 |         files[] = it | 
 | 213 |     } | 
 | 214 |     return files | 
 | 215 | } | 
 | 216 |  | 
 | 217 | /** | 
 | 218 |  * Helper method to convert map into form of list of [key,value] to avoid | 
 | 219 |  * unserializable exceptions | 
 | 220 |  * | 
 | 221 |  * @param m Map | 
 | 222 |  */ | 
 | 223 | @NonCPS | 
 | 224 | def entries(m) { | 
 | 225 |     m.collect {k, v -> [k, v]} | 
 | 226 | } | 
 | 227 |  | 
 | 228 | /** | 
 | 229 |  * Opposite of build-in parallel, run map of steps in serial | 
 | 230 |  * | 
| Jakub Josef | 7fb8bbd | 2017-05-15 16:02:44 +0200 | [diff] [blame] | 231 |  * @param steps Map of String<name>: CPSClosure2<step> (or list of closures) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 232 |  */ | 
 | 233 | def serial(steps) { | 
 | 234 |     stepsArray = entries(steps) | 
 | 235 |     for (i=0; i < stepsArray.size; i++) { | 
| Jakub Josef | d31de30 | 2017-05-15 13:59:18 +0200 | [diff] [blame] | 236 |         def step = stepsArray[i] | 
| Jakub Josef | 7fb8bbd | 2017-05-15 16:02:44 +0200 | [diff] [blame] | 237 |         def dummySteps = [:] | 
 | 238 |         def stepKey | 
| Jakub Josef | 228aae9 | 2017-05-15 19:04:43 +0200 | [diff] [blame] | 239 |         if(step[1] instanceof List || step[1] instanceof Map){ | 
| Jakub Josef | 538be16 | 2017-05-15 19:11:48 +0200 | [diff] [blame] | 240 |             for(j=0;j < step[1].size(); j++){ | 
| Jakub Josef | 7fb8bbd | 2017-05-15 16:02:44 +0200 | [diff] [blame] | 241 |                 if(step[1] instanceof List){ | 
 | 242 |                     stepKey = j | 
 | 243 |                 }else if(step[1] instanceof Map){ | 
 | 244 |                     stepKey = step[1].keySet()[j] | 
 | 245 |                 } | 
 | 246 |                 dummySteps.put("step-${step[0]}-${stepKey}",step[1][stepKey]) | 
| Jakub Josef | d31de30 | 2017-05-15 13:59:18 +0200 | [diff] [blame] | 247 |             } | 
 | 248 |         }else{ | 
 | 249 |             dummySteps.put(step[0], step[1]) | 
 | 250 |         } | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 251 |         parallel dummySteps | 
 | 252 |     } | 
 | 253 | } | 
 | 254 |  | 
 | 255 | /** | 
| Jakub Josef | 7fb8bbd | 2017-05-15 16:02:44 +0200 | [diff] [blame] | 256 |  * Partition given list to list of small lists | 
 | 257 |  * @param inputList input list | 
 | 258 |  * @param partitionSize (partition size, optional, default 5) | 
 | 259 |  */ | 
 | 260 | def partitionList(inputList, partitionSize=5){ | 
 | 261 |   List<List<String>> partitions = new ArrayList<>(); | 
 | 262 |   for (int i=0; i<inputList.size(); i += partitionSize) { | 
 | 263 |       partitions.add(new ArrayList<String>(inputList.subList(i, Math.min(i + partitionSize, inputList.size())))); | 
 | 264 |   } | 
 | 265 |   return partitions | 
 | 266 | } | 
 | 267 |  | 
 | 268 | /** | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 269 |  * Get password credentials from store | 
 | 270 |  * | 
 | 271 |  * @param id    Credentials name | 
 | 272 |  */ | 
 | 273 | def getPasswordCredentials(id) { | 
| Alexander Evseev | bc1fea4 | 2017-12-13 10:03:03 +0100 | [diff] [blame] | 274 |     return getCredentialsById(id, 'password') | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 275 | } | 
 | 276 |  | 
 | 277 | /** | 
 | 278 |  * Get SSH credentials from store | 
 | 279 |  * | 
 | 280 |  * @param id    Credentials name | 
 | 281 |  */ | 
 | 282 | def getSshCredentials(id) { | 
| Alexander Evseev | bc1fea4 | 2017-12-13 10:03:03 +0100 | [diff] [blame] | 283 |     return getCredentialsById(id, 'sshKey') | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 284 | } | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 285 |  | 
 | 286 | /** | 
 | 287 |  * Tests Jenkins instance for existence of plugin with given name | 
 | 288 |  * @param pluginName plugin short name to test | 
 | 289 |  * @return boolean result | 
 | 290 |  */ | 
 | 291 | @NonCPS | 
 | 292 | def jenkinsHasPlugin(pluginName){ | 
 | 293 |     return Jenkins.instance.pluginManager.plugins.collect{p -> p.shortName}.contains(pluginName) | 
 | 294 | } | 
 | 295 |  | 
 | 296 | @NonCPS | 
 | 297 | def _needNotification(notificatedTypes, buildStatus, jobName) { | 
 | 298 |     if(notificatedTypes && notificatedTypes.contains("onchange")){ | 
 | 299 |         if(jobName){ | 
 | 300 |             def job = Jenkins.instance.getItem(jobName) | 
 | 301 |             def numbuilds = job.builds.size() | 
 | 302 |             if (numbuilds > 0){ | 
 | 303 |                 //actual build is first for some reasons, so last finished build is second | 
 | 304 |                 def lastBuild = job.builds[1] | 
 | 305 |                 if(lastBuild){ | 
 | 306 |                     if(lastBuild.result.toString().toLowerCase().equals(buildStatus)){ | 
 | 307 |                         println("Build status didn't changed since last build, not sending notifications") | 
 | 308 |                         return false; | 
 | 309 |                     } | 
 | 310 |                 } | 
 | 311 |             } | 
 | 312 |         } | 
 | 313 |     }else if(!notificatedTypes.contains(buildStatus)){ | 
 | 314 |         return false; | 
 | 315 |     } | 
 | 316 |     return true; | 
 | 317 | } | 
 | 318 |  | 
 | 319 | /** | 
 | 320 |  * Send notification to all enabled notifications services | 
 | 321 |  * @param buildStatus message type (success, warning, error), null means SUCCESSFUL | 
 | 322 |  * @param msgText message text | 
 | 323 |  * @param enabledNotifications list of enabled notification types, types: slack, hipchat, email, default empty | 
 | 324 |  * @param notificatedTypes types of notifications will be sent, default onchange - notificate if current build result not equal last result; | 
 | 325 |  *                         otherwise use - ["success","unstable","failed"] | 
 | 326 |  * @param jobName optional job name param, if empty env.JOB_NAME will be used | 
| Jakub Josef | d057115 | 2017-07-17 14:11:39 +0200 | [diff] [blame] | 327 |  * @param buildNumber build number param, if empty env.BUILD_NUM will be used | 
 | 328 |  * @param buildUrl build url param, if empty env.BUILD_URL will be used | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 329 |  * @param mailFrom mail FROM param, if empty "jenkins" will be used, it's mandatory for sending email notifications | 
| Jakub Josef | d057115 | 2017-07-17 14:11:39 +0200 | [diff] [blame] | 330 |  * @param mailTo mail TO param, it's mandatory for sending email notifications, this option enable mail notification | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 331 |  */ | 
 | 332 | def sendNotification(buildStatus, msgText="", enabledNotifications = [], notificatedTypes=["onchange"], jobName=null, buildNumber=null, buildUrl=null, mailFrom="jenkins", mailTo=null){ | 
 | 333 |     // Default values | 
 | 334 |     def colorName = 'blue' | 
 | 335 |     def colorCode = '#0000FF' | 
 | 336 |     def buildStatusParam = buildStatus != null && buildStatus != "" ? buildStatus : "SUCCESS" | 
 | 337 |     def jobNameParam = jobName != null && jobName != "" ? jobName : env.JOB_NAME | 
 | 338 |     def buildNumberParam = buildNumber != null && buildNumber != "" ? buildNumber : env.BUILD_NUMBER | 
 | 339 |     def buildUrlParam = buildUrl != null && buildUrl != "" ? buildUrl : env.BUILD_URL | 
 | 340 |     def subject = "${buildStatusParam}: Job '${jobNameParam} [${buildNumberParam}]'" | 
 | 341 |     def summary = "${subject} (${buildUrlParam})" | 
 | 342 |  | 
 | 343 |     if(msgText != null && msgText != ""){ | 
 | 344 |         summary+="\n${msgText}" | 
 | 345 |     } | 
 | 346 |     if(buildStatusParam.toLowerCase().equals("success")){ | 
 | 347 |         colorCode = "#00FF00" | 
 | 348 |         colorName = "green" | 
 | 349 |     }else if(buildStatusParam.toLowerCase().equals("unstable")){ | 
 | 350 |         colorCode = "#FFFF00" | 
 | 351 |         colorName = "yellow" | 
 | 352 |     }else if(buildStatusParam.toLowerCase().equals("failure")){ | 
 | 353 |         colorCode = "#FF0000" | 
 | 354 |         colorName = "red" | 
 | 355 |     } | 
 | 356 |     if(_needNotification(notificatedTypes, buildStatusParam.toLowerCase(), jobNameParam)){ | 
 | 357 |         if(enabledNotifications.contains("slack") && jenkinsHasPlugin("slack")){ | 
 | 358 |             try{ | 
 | 359 |                 slackSend color: colorCode, message: summary | 
 | 360 |             }catch(Exception e){ | 
 | 361 |                 println("Calling slack plugin failed") | 
 | 362 |                 e.printStackTrace() | 
 | 363 |             } | 
 | 364 |         } | 
 | 365 |         if(enabledNotifications.contains("hipchat") && jenkinsHasPlugin("hipchat")){ | 
 | 366 |             try{ | 
 | 367 |                 hipchatSend color: colorName.toUpperCase(), message: summary | 
 | 368 |             }catch(Exception e){ | 
 | 369 |                 println("Calling hipchat plugin failed") | 
 | 370 |                 e.printStackTrace() | 
 | 371 |             } | 
 | 372 |         } | 
 | 373 |         if(enabledNotifications.contains("email") && mailTo != null && mailTo != "" && mailFrom != null && mailFrom != ""){ | 
 | 374 |             try{ | 
 | 375 |                 mail body: summary, from: mailFrom, subject: subject, to: mailTo | 
 | 376 |             }catch(Exception e){ | 
 | 377 |                 println("Sending mail plugin failed") | 
 | 378 |                 e.printStackTrace() | 
 | 379 |             } | 
 | 380 |         } | 
 | 381 |     } | 
| Filip Pytloun | 49d6630 | 2017-03-06 10:26:22 +0100 | [diff] [blame] | 382 | } | 
| chnyda | 4e5ac79 | 2017-03-14 15:24:18 +0100 | [diff] [blame] | 383 |  | 
 | 384 | /** | 
 | 385 |  * Execute linux command and catch nth element | 
 | 386 |  * @param cmd command to execute | 
 | 387 |  * @param index index to retrieve | 
 | 388 |  * @return index-th element | 
 | 389 |  */ | 
 | 390 |  | 
 | 391 | def cutOrDie(cmd, index) | 
 | 392 | { | 
 | 393 |     def common = new com.mirantis.mk.Common() | 
 | 394 |     def output | 
 | 395 |     try { | 
 | 396 |       output = sh(script: cmd, returnStdout: true) | 
 | 397 |       def result = output.tokenize(" ")[index] | 
 | 398 |       return result; | 
 | 399 |     } catch (Exception e) { | 
 | 400 |       common.errorMsg("Failed to execute cmd: ${cmd}\n output: ${output}") | 
 | 401 |     } | 
| Filip Pytloun | 81c864d | 2017-03-21 15:19:30 +0100 | [diff] [blame] | 402 | } | 
| Tomáš Kukrál | 767dd73 | 2017-03-23 10:38:59 +0100 | [diff] [blame] | 403 |  | 
 | 404 | /** | 
 | 405 |  * Check variable contains keyword | 
 | 406 |  * @param variable keywork is searched (contains) here | 
 | 407 |  * @param keyword string to look for | 
 | 408 |  * @return True if variable contains keyword (case insensitive), False if do not contains or any of input isn't a string | 
 | 409 |  */ | 
 | 410 |  | 
 | 411 | def checkContains(variable, keyword) { | 
| Jakub Josef | 7a8dea2 | 2017-03-23 19:51:32 +0100 | [diff] [blame] | 412 |     if(env.getEnvironment().containsKey(variable)){ | 
 | 413 |         return env[variable] && env[variable].toLowerCase().contains(keyword.toLowerCase()) | 
| Tomáš Kukrál | 767dd73 | 2017-03-23 10:38:59 +0100 | [diff] [blame] | 414 |     } else { | 
| Tomáš Kukrál | c76c1e0 | 2017-03-23 19:06:59 +0100 | [diff] [blame] | 415 |         return false | 
| Tomáš Kukrál | 767dd73 | 2017-03-23 10:38:59 +0100 | [diff] [blame] | 416 |     } | 
 | 417 | } | 
| Jakub Josef | a877db5 | 2017-04-05 14:22:30 +0200 | [diff] [blame] | 418 |  | 
 | 419 | /** | 
 | 420 |  * Parse JSON string to hashmap | 
 | 421 |  * @param jsonString input JSON string | 
 | 422 |  * @return created hashmap | 
 | 423 |  */ | 
 | 424 | def parseJSON(jsonString){ | 
 | 425 |    def m = [:] | 
| Jakub Josef | b7ab847 | 2017-04-05 14:56:53 +0200 | [diff] [blame] | 426 |    def lazyMap = new JsonSlurperClassic().parseText(jsonString) | 
| Jakub Josef | a877db5 | 2017-04-05 14:22:30 +0200 | [diff] [blame] | 427 |    m.putAll(lazyMap) | 
 | 428 |    return m | 
 | 429 | } | 
| Jakub Josef | ed239cd | 2017-05-09 15:27:33 +0200 | [diff] [blame] | 430 |  | 
 | 431 | /** | 
 | 432 |  * Test pipeline input parameter existence and validity (not null and not empty string) | 
 | 433 |  * @param paramName input parameter name (usually uppercase) | 
 | 434 |  */ | 
 | 435 | def validInputParam(paramName){ | 
 | 436 |     return env.getEnvironment().containsKey(paramName) && env[paramName] != null && env[paramName] != "" | 
| Tomáš Kukrál | d34fe87 | 2017-06-13 10:50:50 +0200 | [diff] [blame] | 437 | } | 
 | 438 |  | 
 | 439 | /** | 
 | 440 |  * Take list of hashmaps and count number of hashmaps with parameter equals eq | 
 | 441 |  * @param lm list of hashmaps | 
 | 442 |  * @param param define parameter of hashmap to read and compare | 
 | 443 |  * @param eq desired value of hashmap parameter | 
 | 444 |  * @return count of hashmaps meeting defined condition | 
 | 445 |  */ | 
 | 446 |  | 
 | 447 | @NonCPS | 
 | 448 | def countHashMapEquals(lm, param, eq) { | 
| Tomáš Kukrál | 5dd1207 | 2017-06-13 15:54:44 +0200 | [diff] [blame] | 449 |     return lm.stream().filter{i -> i[param].equals(eq)}.collect(java.util.stream.Collectors.counting()) | 
| Tomáš Kukrál | d34fe87 | 2017-06-13 10:50:50 +0200 | [diff] [blame] | 450 | } | 
| Vasyl Saienko | fb055b1 | 2017-11-23 18:15:23 +0200 | [diff] [blame^] | 451 |  | 
 | 452 | /** | 
 | 453 |  * Execute shell command and return stdout, stderr and status | 
 | 454 |  * | 
 | 455 |  * @param cmd Command to execute | 
 | 456 |  * @return map with stdout, stderr, status keys | 
 | 457 |  */ | 
 | 458 |  | 
 | 459 | def shCmdStatus(cmd) { | 
 | 460 |     def res = [:] | 
 | 461 |     def stderr = sh(script: 'mktemp', returnStdout: true).trim() | 
 | 462 |     def stdout = sh(script: 'mktemp', returnStdout: true).trim() | 
 | 463 |  | 
 | 464 |     try { | 
 | 465 |         def status = sh(script:"${cmd} 1>${stdout} 2>${stderr}", returnStatus: true) | 
 | 466 |         res['stderr'] = sh(script: "cat ${stderr}", returnStdout: true) | 
 | 467 |         res['stdout'] = sh(script: "cat ${stdout}", returnStdout: true) | 
 | 468 |         res['status'] = status | 
 | 469 |     } finally { | 
 | 470 |         sh(script: "rm ${stderr}", returnStdout: true) | 
 | 471 |         sh(script: "rm ${stdout}", returnStdout: true) | 
 | 472 |     } | 
 | 473 |  | 
 | 474 |     return res | 
 | 475 | } |