| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 1 | package com.mirantis.mk | 
 | 2 |  | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 3 | import com.cloudbees.groovy.cps.NonCPS | 
| Jakub Josef | b77c081 | 2017-03-27 14:11:01 +0200 | [diff] [blame] | 4 | import java.util.stream.Collectors | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 5 | /** | 
 | 6 |  * Salt functions | 
 | 7 |  * | 
 | 8 | */ | 
 | 9 |  | 
 | 10 | /** | 
 | 11 |  * Salt connection and context parameters | 
 | 12 |  * | 
 | 13 |  * @param url                 Salt API server URL | 
 | 14 |  * @param credentialsID       ID of credentials store entry | 
 | 15 |  */ | 
 | 16 | def connection(url, credentialsId = "salt") { | 
| Tomáš Kukrál | 6c04bd0 | 2017-03-01 22:18:52 +0100 | [diff] [blame] | 17 |     def common = new com.mirantis.mk.Common() | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 18 |     params = [ | 
 | 19 |         "url": url, | 
 | 20 |         "credentialsId": credentialsId, | 
 | 21 |         "authToken": null, | 
 | 22 |         "creds": common.getCredentials(credentialsId) | 
 | 23 |     ] | 
 | 24 |     params["authToken"] = saltLogin(params) | 
 | 25 |  | 
 | 26 |     return params | 
 | 27 | } | 
 | 28 |  | 
 | 29 | /** | 
 | 30 |  * Login to Salt API, return auth token | 
 | 31 |  * | 
 | 32 |  * @param master   Salt connection object | 
 | 33 |  */ | 
 | 34 | def saltLogin(master) { | 
| Tomáš Kukrál | 7bec053 | 2017-02-20 15:39:31 +0100 | [diff] [blame] | 35 |     def http = new com.mirantis.mk.Http() | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 36 |     data = [ | 
 | 37 |         'username': master.creds.username, | 
 | 38 |         'password': master.creds.password.toString(), | 
 | 39 |         'eauth': 'pam' | 
 | 40 |     ] | 
| Tomáš Kukrál | 7bec053 | 2017-02-20 15:39:31 +0100 | [diff] [blame] | 41 |     authToken = http.restGet(master, '/login', data)['return'][0]['token'] | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 42 |     return authToken | 
 | 43 | } | 
 | 44 |  | 
 | 45 | /** | 
 | 46 |  * Run action using Salt API | 
 | 47 |  * | 
 | 48 |  * @param master   Salt connection object | 
 | 49 |  * @param client   Client type | 
 | 50 |  * @param target   Target specification, eg. for compound matches by Pillar | 
 | 51 |  *                 data: ['expression': 'I@openssh:server', 'type': 'compound']) | 
 | 52 |  * @param function Function to execute (eg. "state.sls") | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 53 |  * @param batch    Batch param to salt (integer or string with percents) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 54 |  * @param args     Additional arguments to function | 
 | 55 |  * @param kwargs   Additional key-value arguments to function | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 56 |  * @param timeout  Additional argument salt api timeout | 
| Vasyl Saienko | e36ab7c | 2017-07-17 14:35:48 +0300 | [diff] [blame] | 57 |  * @param read_timeout http session read timeout | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 58 |  */ | 
 | 59 | @NonCPS | 
| Vasyl Saienko | e36ab7c | 2017-07-17 14:35:48 +0300 | [diff] [blame] | 60 | def runSaltCommand(master, client, target, function, batch = null, args = null, kwargs = null, timeout = -1, read_timeout = -1) { | 
| iberezovskiy | d4240b5 | 2017-02-20 17:18:28 +0400 | [diff] [blame] | 61 |     def http = new com.mirantis.mk.Http() | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 62 |  | 
 | 63 |     data = [ | 
 | 64 |         'tgt': target.expression, | 
 | 65 |         'fun': function, | 
 | 66 |         'client': client, | 
 | 67 |         'expr_form': target.type, | 
 | 68 |     ] | 
 | 69 |  | 
| Jakub Josef | 5f83821 | 2017-04-06 12:43:58 +0200 | [diff] [blame] | 70 |     if(batch != null && ( (batch instanceof Integer && batch > 0) || (batch instanceof String && batch.contains("%")))){ | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 71 |         data['client']= "local_batch" | 
 | 72 |         data['batch'] = batch | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 73 |     } | 
 | 74 |  | 
 | 75 |     if (args) { | 
 | 76 |         data['arg'] = args | 
 | 77 |     } | 
 | 78 |  | 
 | 79 |     if (kwargs) { | 
 | 80 |         data['kwarg'] = kwargs | 
 | 81 |     } | 
 | 82 |  | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 83 |     if (timeout != -1) { | 
 | 84 |         data['timeout'] = timeout | 
 | 85 |     } | 
 | 86 |  | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 87 |     headers = [ | 
 | 88 |       'X-Auth-Token': "${master.authToken}" | 
 | 89 |     ] | 
 | 90 |  | 
| Vasyl Saienko | e36ab7c | 2017-07-17 14:35:48 +0300 | [diff] [blame] | 91 |     return http.sendHttpPostRequest("${master.url}/", data, headers, read_timeout) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 92 | } | 
 | 93 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 94 | /** | 
 | 95 |  * Return pillar for given master and target | 
 | 96 |  * @param master Salt connection object | 
 | 97 |  * @param target Get pillar target | 
 | 98 |  * @param pillar pillar name (optional) | 
 | 99 |  * @return output of salt command | 
 | 100 |  */ | 
| Ales Komarek | cec24d4 | 2017-03-08 10:25:45 +0100 | [diff] [blame] | 101 | def getPillar(master, target, pillar = null) { | 
| Tomáš Kukrál | d258970 | 2017-03-10 16:30:46 +0100 | [diff] [blame] | 102 |     if (pillar != null) { | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 103 |         return runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'pillar.get', null, [pillar.replace('.', ':')]) | 
| Tomáš Kukrál | d258970 | 2017-03-10 16:30:46 +0100 | [diff] [blame] | 104 |     } else { | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 105 |         return runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'pillar.data') | 
| Ales Komarek | a3c7e50 | 2017-03-13 11:20:44 +0100 | [diff] [blame] | 106 |     } | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 107 | } | 
 | 108 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 109 | /** | 
 | 110 |  * Return grain for given master and target | 
 | 111 |  * @param master Salt connection object | 
 | 112 |  * @param target Get grain target | 
 | 113 |  * @param grain grain name (optional) | 
 | 114 |  * @return output of salt command | 
 | 115 |  */ | 
| Ales Komarek | cec24d4 | 2017-03-08 10:25:45 +0100 | [diff] [blame] | 116 | def getGrain(master, target, grain = null) { | 
 | 117 |     if(grain != null) { | 
| Jiri Broulik | 852dfd5 | 2017-05-16 13:38:55 +0200 | [diff] [blame] | 118 |         return runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'grains.item', null, [grain]) | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 119 |     } else { | 
| Jiri Broulik | 852dfd5 | 2017-05-16 13:38:55 +0200 | [diff] [blame] | 120 |         return runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'grains.items') | 
| Ales Komarek | cec24d4 | 2017-03-08 10:25:45 +0100 | [diff] [blame] | 121 |     } | 
| Ales Komarek | cec24d4 | 2017-03-08 10:25:45 +0100 | [diff] [blame] | 122 | } | 
 | 123 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 124 | /** | 
 | 125 |  * Enforces state on given master and target | 
 | 126 |  * @param master Salt connection object | 
 | 127 |  * @param target State enforcing target | 
 | 128 |  * @param state Salt state | 
 | 129 |  * @param output print output (optional, default true) | 
 | 130 |  * @param failOnError throw exception on salt state result:false (optional, default true) | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 131 |  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch) | 
| Vasyl Saienko | e36ab7c | 2017-07-17 14:35:48 +0300 | [diff] [blame] | 132 |  * @param read_timeout http session read timeout | 
 | 133 |  * @param retries Retry count for salt state. | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 134 |  * @return output of salt command | 
 | 135 |  */ | 
| Vasyl Saienko | e36ab7c | 2017-07-17 14:35:48 +0300 | [diff] [blame] | 136 | def enforceState(master, target, state, output = true, failOnError = true, batch = null, optional = false, read_timeout=-1, retries=-1) { | 
| Tomáš Kukrál | 6c04bd0 | 2017-03-01 22:18:52 +0100 | [diff] [blame] | 137 |     def common = new com.mirantis.mk.Common() | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 138 |     def run_states | 
| Tomáš Kukrál | 6c04bd0 | 2017-03-01 22:18:52 +0100 | [diff] [blame] | 139 |  | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 140 |     if (state instanceof String) { | 
 | 141 |         run_states = state | 
 | 142 |     } else { | 
 | 143 |         run_states = state.join(',') | 
 | 144 |     } | 
 | 145 |  | 
| Marek Celoud | 6336611 | 2017-07-25 17:27:24 +0200 | [diff] [blame] | 146 |     common.infoMsg("Running state ${run_states} on ${target}") | 
| Vasyl Saienko | e36ab7c | 2017-07-17 14:35:48 +0300 | [diff] [blame] | 147 |     def out | 
 | 148 |  | 
 | 149 |     if (optional == false || testTarget(master, target)){ | 
 | 150 |         if (retries != -1){ | 
 | 151 |             retry(retries){ | 
 | 152 |                 out = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'state.sls', batch, [run_states], null, -1, read_timeout) | 
 | 153 |             } | 
 | 154 |             } | 
 | 155 |         else { | 
 | 156 |             out = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'state.sls', batch, [run_states], null, -1, read_timeout) | 
 | 157 |         } | 
| Martin Polreich | 1c77afa | 2017-07-18 11:27:02 +0200 | [diff] [blame] | 158 |         checkResult(out, failOnError, output) | 
 | 159 |         return out | 
| Martin Polreich | 1c77afa | 2017-07-18 11:27:02 +0200 | [diff] [blame] | 160 |     } else { | 
 | 161 |         common.infoMsg("No Minions matched the target given, but 'optional' param was set to true - Pipeline continues. ") | 
 | 162 |     } | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 163 | } | 
 | 164 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 165 | /** | 
 | 166 |  * Run command on salt minion (salt cmd.run wrapper) | 
 | 167 |  * @param master Salt connection object | 
 | 168 |  * @param target Get pillar target | 
 | 169 |  * @param cmd command | 
| Jakub Josef | 053df39 | 2017-05-03 15:51:05 +0200 | [diff] [blame] | 170 |  * @param checkResponse test command success execution (default true) | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 171 |  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch) | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 172 |  * @param output do you want to print output | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 173 |  * @return output of salt command | 
 | 174 |  */ | 
| Jiri Broulik | 16e9ce7 | 2017-05-17 13:28:31 +0200 | [diff] [blame] | 175 | def cmdRun(master, target, cmd, checkResponse = true, batch=null, output = true) { | 
| Tomáš Kukrál | 6c04bd0 | 2017-03-01 22:18:52 +0100 | [diff] [blame] | 176 |     def common = new com.mirantis.mk.Common() | 
| Jakub Josef | 053df39 | 2017-05-03 15:51:05 +0200 | [diff] [blame] | 177 |     def originalCmd = cmd | 
| Tomáš Kukrál | dfd4b49 | 2017-03-02 12:08:50 +0100 | [diff] [blame] | 178 |     common.infoMsg("Running command ${cmd} on ${target}") | 
| Jakub Josef | 053df39 | 2017-05-03 15:51:05 +0200 | [diff] [blame] | 179 |     if (checkResponse) { | 
 | 180 |       cmd = cmd + " && echo Salt command execution success" | 
 | 181 |     } | 
| Jiri Broulik | 16e9ce7 | 2017-05-17 13:28:31 +0200 | [diff] [blame] | 182 |     def out = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'cmd.run', batch, [cmd]) | 
| Jakub Josef | 053df39 | 2017-05-03 15:51:05 +0200 | [diff] [blame] | 183 |     if (checkResponse) { | 
 | 184 |         // iterate over all affected nodes and check success return code | 
| Jiri Broulik | 16e9ce7 | 2017-05-17 13:28:31 +0200 | [diff] [blame] | 185 |         if (out["return"]){ | 
 | 186 |             for(int i=0;i<out["return"].size();i++){ | 
 | 187 |                 def node = out["return"][i]; | 
| Jakub Josef | 053df39 | 2017-05-03 15:51:05 +0200 | [diff] [blame] | 188 |                 for(int j=0;j<node.size();j++){ | 
 | 189 |                     def nodeKey = node.keySet()[j] | 
 | 190 |                     if (!node[nodeKey].contains("Salt command execution success")) { | 
 | 191 |                         throw new Exception("Execution of cmd ${originalCmd} failed. Server returns: ${node[nodeKey]}") | 
 | 192 |                     } | 
 | 193 |                 } | 
 | 194 |             } | 
 | 195 |         }else{ | 
 | 196 |             throw new Exception("Salt Api response doesn't have return param!") | 
 | 197 |         } | 
 | 198 |     } | 
| Jiri Broulik | 16e9ce7 | 2017-05-17 13:28:31 +0200 | [diff] [blame] | 199 |     if (output == true) { | 
 | 200 |         printSaltCommandResult(out) | 
 | 201 |     } | 
 | 202 |     return out | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 203 | } | 
 | 204 |  | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 205 |  | 
 | 206 | /** | 
 | 207 |  * Run command on salt minion (salt cmd.run wrapper) | 
 | 208 |  * @param master Salt connection object | 
 | 209 |  * @param target Get pillar target | 
 | 210 |  * @param minion_name unique identification of a minion in salt-key command output | 
 | 211 |  * @param waitUntilPresent return after the minion becomes present (default true) | 
 | 212 |  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch) | 
 | 213 |  * @param output print salt command (default true) | 
 | 214 |  * @return output of salt command | 
 | 215 |  */ | 
| Jakub Josef | 115a78f | 2017-07-18 15:04:00 +0200 | [diff] [blame] | 216 | def minionPresent(master, target, minion_name, waitUntilPresent = true, batch=null, output = true) { | 
| Jiri Broulik | cf1f233 | 2017-07-25 11:30:03 +0200 | [diff] [blame] | 217 |     return commandStatus(master, target, 'salt-key | grep ' + minion_name, minion_name, true, waitUntilPresent, batch, output) | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 218 | } | 
 | 219 |  | 
 | 220 | /** | 
 | 221 |  * Run command on salt minion (salt cmd.run wrapper) | 
 | 222 |  * @param master Salt connection object | 
 | 223 |  * @param target Get pillar target | 
 | 224 |  * @param cmd name of a service | 
 | 225 |  * @param correct_state string that command must contain if status is in correct state (optional, default 'running') | 
| Jiri Broulik | cf1f233 | 2017-07-25 11:30:03 +0200 | [diff] [blame] | 226 |  * @param find bool value if it is suppose to find some string in the output or the cmd should return empty string (optional, default true) | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 227 |  * @param waitUntilOk return after the minion becomes present (optional, default true) | 
 | 228 |  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch) | 
 | 229 |  * @param output print salt command (default true) | 
 | 230 |  * @return output of salt command | 
 | 231 |  */ | 
| Jiri Broulik | d0c2757 | 2017-07-24 20:01:10 +0200 | [diff] [blame] | 232 | def commandStatus(master, target, cmd, correct_state='running', find = true, waitUntilOk = true, batch=null, output = true, maxRetries = 200) { | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 233 |     def common = new com.mirantis.mk.Common() | 
 | 234 |     common.infoMsg("Checking if status of verification command ${cmd} on ${target} is in correct state") | 
 | 235 |     if (waitUntilOk){ | 
 | 236 |         def count = 0 | 
 | 237 |         while(count < maxRetries) { | 
| Jiri Broulik | d0c2757 | 2017-07-24 20:01:10 +0200 | [diff] [blame] | 238 |             def out = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'cmd.shell', batch, [cmd], null, 5) | 
| Jakub Josef | 115a78f | 2017-07-18 15:04:00 +0200 | [diff] [blame] | 239 |             def resultMap = out["return"][0] | 
 | 240 |             def result = resultMap.get(resultMap.keySet()[0]) | 
| Jiri Broulik | d0c2757 | 2017-07-24 20:01:10 +0200 | [diff] [blame] | 241 |             // if the goal is to find some string in output of the command | 
 | 242 |             if (find) { | 
 | 243 |                 if(result == null || result.isEmpty()) { result='' } | 
 | 244 |                 if (result.toLowerCase().contains(correct_state.toLowerCase())) { | 
 | 245 |                     if (output) { | 
 | 246 |                         printSaltCommandResult(out) | 
 | 247 |                     } | 
 | 248 |                     return out | 
 | 249 |                 } | 
 | 250 |  | 
 | 251 |             // else the goal is to not find any string in output of the command | 
 | 252 |             } else { | 
 | 253 |                 if(result instanceof String && result.isEmpty()) { | 
 | 254 |                     return out | 
 | 255 |                 } | 
 | 256 |             } | 
 | 257 |             count++ | 
 | 258 |             sleep(time: 500, unit: 'MILLISECONDS') | 
 | 259 |             common.infoMsg("Waiting for ${cmd} on ${target} to be in correct state") | 
 | 260 |         } | 
 | 261 |     } else { | 
 | 262 |         def out = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'cmd.shell', batch, [cmd]) | 
 | 263 |         def resultMap = out["return"][0] | 
 | 264 |         def result = resultMap.get(resultMap.keySet()[0]) | 
 | 265 |  | 
 | 266 |         // if the goal is to find some string in output of the command | 
 | 267 |         if (find) { | 
 | 268 |             if(result == null || result.isEmpty()) { result='' } | 
| Jakub Josef | 115a78f | 2017-07-18 15:04:00 +0200 | [diff] [blame] | 269 |             if (result.toLowerCase().contains(correct_state.toLowerCase())) { | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 270 |                 if (output) { | 
 | 271 |                     printSaltCommandResult(out) | 
 | 272 |                 } | 
 | 273 |                 return out | 
 | 274 |             } | 
| Jiri Broulik | d0c2757 | 2017-07-24 20:01:10 +0200 | [diff] [blame] | 275 |  | 
 | 276 |         // else the goal is to not find any string in output of the command | 
 | 277 |         } else { | 
 | 278 |             if(result instanceof String && result.isEmpty()) { | 
 | 279 |                 return out | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 280 |             } | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 281 |         } | 
 | 282 |     } | 
 | 283 |     // otherwise throw exception | 
| Jiri Broulik | d0c2757 | 2017-07-24 20:01:10 +0200 | [diff] [blame] | 284 |     common.errorMsg("Status of command ${cmd} on ${target} failed, please check it.") | 
| Jiri Broulik | 2c69f3d | 2017-07-18 14:23:58 +0200 | [diff] [blame] | 285 |     throw new Exception("${cmd} signals failure of status check!") | 
 | 286 | } | 
 | 287 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 288 | /** | 
 | 289 |  * Perform complete salt sync between master and target | 
 | 290 |  * @param master Salt connection object | 
 | 291 |  * @param target Get pillar target | 
 | 292 |  * @return output of salt command | 
 | 293 |  */ | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 294 | def syncAll(master, target) { | 
| Filip Pytloun | 5a7f7fd | 2017-02-27 18:50:25 +0100 | [diff] [blame] | 295 |     return runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'saltutil.sync_all') | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 296 | } | 
 | 297 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 298 | /** | 
 | 299 |  * Enforce highstate on given targets | 
 | 300 |  * @param master Salt connection object | 
 | 301 |  * @param target Highstate enforcing target | 
 | 302 |  * @param output print output (optional, default true) | 
 | 303 |  * @param failOnError throw exception on salt state result:false (optional, default true) | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 304 |  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch) | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 305 |  * @return output of salt command | 
 | 306 |  */ | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 307 | def enforceHighstate(master, target, output = false, failOnError = true, batch = null) { | 
 | 308 |     def out = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'state.highstate', batch) | 
| Alexander Noskov | 657ccfc | 2017-07-14 11:35:52 +0000 | [diff] [blame] | 309 |     def common = new com.mirantis.mk.Common() | 
 | 310 |  | 
| Marek Celoud | 6336611 | 2017-07-25 17:27:24 +0200 | [diff] [blame] | 311 |     common.infoMsg("Running state highstate on ${target}") | 
| Alexander Noskov | 657ccfc | 2017-07-14 11:35:52 +0000 | [diff] [blame] | 312 |  | 
| Jakub Josef | 374beb7 | 2017-04-27 15:45:09 +0200 | [diff] [blame] | 313 |     checkResult(out, failOnError, output) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 314 |     return out | 
 | 315 | } | 
 | 316 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 317 | /** | 
| Ales Komarek | 5276ebe | 2017-03-16 08:46:34 +0100 | [diff] [blame] | 318 |  * Get running minions IDs according to the target | 
 | 319 |  * @param master Salt connection object | 
 | 320 |  * @param target Get minions target | 
 | 321 |  * @return list of active minions fitin | 
 | 322 |  */ | 
 | 323 | def getMinions(master, target) { | 
| Tomáš Kukrál | 18ac50f | 2017-07-13 10:22:09 +0200 | [diff] [blame] | 324 |     def minionsRaw = runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'test.ping') | 
| Ales Komarek | 5276ebe | 2017-03-16 08:46:34 +0100 | [diff] [blame] | 325 |     return new ArrayList<String>(minionsRaw['return'][0].keySet()) | 
 | 326 | } | 
 | 327 |  | 
 | 328 |  | 
 | 329 | /** | 
| Tomáš Kukrál | b12ff9f | 2017-07-12 12:32:34 +0200 | [diff] [blame] | 330 |  * Test if there are any minions to target | 
 | 331 |  * @param master Salt connection object | 
 | 332 |  * @param target Target to test | 
| vrovachev | 1c4770b | 2017-07-05 13:25:21 +0400 | [diff] [blame] | 333 |  * @return bool indicating if target was succesful | 
| Tomáš Kukrál | b12ff9f | 2017-07-12 12:32:34 +0200 | [diff] [blame] | 334 |  */ | 
 | 335 |  | 
 | 336 | def testTarget(master, target) { | 
 | 337 |     return getMinions(master, target).size() > 0 | 
 | 338 | } | 
 | 339 |  | 
 | 340 | /** | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 341 |  * Generates node key using key.gen_accept call | 
 | 342 |  * @param master Salt connection object | 
 | 343 |  * @param target Key generating target | 
 | 344 |  * @param host Key generating host | 
 | 345 |  * @param keysize generated key size (optional, default 4096) | 
 | 346 |  * @return output of salt command | 
 | 347 |  */ | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 348 | def generateNodeKey(master, target, host, keysize = 4096) { | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 349 |     return runSaltCommand(master, 'wheel', target, 'key.gen_accept', [host], ['keysize': keysize]) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 350 | } | 
 | 351 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 352 | /** | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 353 |  * Generates node reclass metadata | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 354 |  * @param master Salt connection object | 
 | 355 |  * @param target Metadata generating target | 
 | 356 |  * @param host Metadata generating host | 
 | 357 |  * @param classes Reclass classes | 
 | 358 |  * @param parameters Reclass parameters | 
 | 359 |  * @return output of salt command | 
 | 360 |  */ | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 361 | def generateNodeMetadata(master, target, host, classes, parameters) { | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 362 |     return runSaltCommand(master, 'local', target, 'reclass.node_create', [host, '_generated'], ['classes': classes, 'parameters': parameters]) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 363 | } | 
 | 364 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 365 | /** | 
 | 366 |  * Run salt orchestrate on given targets | 
 | 367 |  * @param master Salt connection object | 
 | 368 |  * @param target Orchestration target | 
 | 369 |  * @param orchestrate Salt orchestrate params | 
 | 370 |  * @return output of salt command | 
 | 371 |  */ | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 372 | def orchestrateSystem(master, target, orchestrate) { | 
 | 373 |     return runSaltCommand(master, 'runner', target, 'state.orchestrate', [orchestrate]) | 
 | 374 | } | 
 | 375 |  | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 376 | /** | 
 | 377 |  * Run salt process step | 
 | 378 |  * @param master Salt connection object | 
 | 379 |  * @param tgt Salt process step target | 
 | 380 |  * @param fun Salt process step function | 
 | 381 |  * @param arg process step arguments (optional, default []) | 
| Jakub Josef | 2f25cf2 | 2017-03-28 13:34:57 +0200 | [diff] [blame] | 382 |  * @param batch salt batch parameter integer or string with percents (optional, default null - disable batch) | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 383 |  * @param output print output (optional, default false) | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 384 |  * @param timeout  Additional argument salt api timeout | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 385 |  * @return output of salt command | 
 | 386 |  */ | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 387 | def runSaltProcessStep(master, tgt, fun, arg = [], batch = null, output = false, timeout = -1) { | 
| Tomáš Kukrál | 6c04bd0 | 2017-03-01 22:18:52 +0100 | [diff] [blame] | 388 |     def common = new com.mirantis.mk.Common() | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 389 |     def salt = new com.mirantis.mk.Salt() | 
| Tomáš Kukrál | adb4ecd | 2017-03-02 10:06:36 +0100 | [diff] [blame] | 390 |     def out | 
 | 391 |  | 
| Marek Celoud | 6336611 | 2017-07-25 17:27:24 +0200 | [diff] [blame] | 392 |     common.infoMsg("Running step ${fun} ${arg} on ${tgt}") | 
| Tomáš Kukrál | 6c04bd0 | 2017-03-01 22:18:52 +0100 | [diff] [blame] | 393 |  | 
| Filip Pytloun | f0435c0 | 2017-03-02 17:48:54 +0100 | [diff] [blame] | 394 |     if (batch == true) { | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 395 |         out = runSaltCommand(master, 'local_batch', ['expression': tgt, 'type': 'compound'], fun, String.valueOf(batch), arg, null, timeout) | 
| Tomáš Kukrál | adb4ecd | 2017-03-02 10:06:36 +0100 | [diff] [blame] | 396 |     } else { | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 397 |         out = runSaltCommand(master, 'local', ['expression': tgt, 'type': 'compound'], fun, batch, arg, null, timeout) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 398 |     } | 
| Tomáš Kukrál | adb4ecd | 2017-03-02 10:06:36 +0100 | [diff] [blame] | 399 |  | 
| Tomáš Kukrál | f5dda64 | 2017-03-02 14:22:59 +0100 | [diff] [blame] | 400 |     if (output == true) { | 
| Jiri Broulik | 48544be | 2017-06-14 18:33:54 +0200 | [diff] [blame] | 401 |         salt.printSaltCommandResult(out) | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 402 |     } | 
| Jiri Broulik | ae19c26 | 2017-05-16 19:06:52 +0200 | [diff] [blame] | 403 |     return out | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 404 | } | 
 | 405 |  | 
 | 406 | /** | 
 | 407 |  * Check result for errors and throw exception if any found | 
 | 408 |  * | 
 | 409 |  * @param result    Parsed response of Salt API | 
| Jakub Josef | 8021c00 | 2017-03-27 15:41:28 +0200 | [diff] [blame] | 410 |  * @param failOnError Do you want to throw exception if salt-call fails (optional, default true) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 411 |  * @param printResults Do you want to print salt results (optional, default true) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 412 |  * @param printOnlyChanges If true (default), print only changed resources | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 413 |  */ | 
| Jakub Josef | 374beb7 | 2017-04-27 15:45:09 +0200 | [diff] [blame] | 414 | def checkResult(result, failOnError = true, printResults = true, printOnlyChanges = true) { | 
| Jakub Josef | 5ade54c | 2017-03-10 16:14:01 +0100 | [diff] [blame] | 415 |     def common = new com.mirantis.mk.Common() | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 416 |     if(result != null){ | 
 | 417 |         if(result['return']){ | 
 | 418 |             for (int i=0;i<result['return'].size();i++) { | 
 | 419 |                 def entry = result['return'][i] | 
 | 420 |                 if (!entry) { | 
 | 421 |                     if (failOnError) { | 
 | 422 |                         throw new Exception("Salt API returned empty response: ${result}") | 
 | 423 |                     } else { | 
 | 424 |                         common.errorMsg("Salt API returned empty response: ${result}") | 
| Jakub Josef | ece32af | 2017-03-14 19:20:08 +0100 | [diff] [blame] | 425 |                     } | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 426 |                 } | 
 | 427 |                 for (int j=0;j<entry.size();j++) { | 
 | 428 |                     def nodeKey = entry.keySet()[j] | 
 | 429 |                     def node=entry[nodeKey] | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 430 |                     def outputResources = [] | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 431 |                     common.infoMsg("Node ${nodeKey} changes:") | 
 | 432 |                     if(node instanceof Map || node instanceof List){ | 
 | 433 |                         for (int k=0;k<node.size();k++) { | 
 | 434 |                             def resource; | 
 | 435 |                             def resKey; | 
 | 436 |                             if(node instanceof Map){ | 
 | 437 |                                 resKey = node.keySet()[k] | 
 | 438 |                             }else if(node instanceof List){ | 
 | 439 |                                 resKey = k | 
 | 440 |                             } | 
 | 441 |                             resource = node[resKey] | 
| Jakub Josef | c4c4020 | 2017-04-28 12:04:24 +0200 | [diff] [blame] | 442 |                            // print | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 443 |                             if(printResults){ | 
 | 444 |                                 if(resource instanceof Map && resource.keySet().contains("result")){ | 
 | 445 |                                     //clean unnesaccary fields | 
 | 446 |                                     if(resource.keySet().contains("__run_num__")){ | 
 | 447 |                                         resource.remove("__run_num__") | 
 | 448 |                                     } | 
 | 449 |                                     if(resource.keySet().contains("__id__")){ | 
 | 450 |                                         resource.remove("__id__") | 
 | 451 |                                     } | 
 | 452 |                                     if(resource.keySet().contains("pchanges")){ | 
 | 453 |                                         resource.remove("pchanges") | 
 | 454 |                                     } | 
 | 455 |                                     if(!resource["result"] || (resource["result"] instanceof String && resource["result"] != "true")){ | 
 | 456 |                                         if(resource["result"] != null){ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 457 |                                             outputResources.add(String.format("Resource: %s\n\u001B[31m%s\u001B[0m", resKey, common.prettify(resource))) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 458 |                                         }else{ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 459 |                                             outputResources.add(String.format("Resource: %s\n\u001B[33m%s\u001B[0m", resKey, common.prettify(resource))) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 460 |                                         } | 
 | 461 |                                     }else{ | 
 | 462 |                                         if(!printOnlyChanges || resource.changes.size() > 0){ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 463 |                                             outputResources.add(String.format("Resource: %s\n\u001B[32m%s\u001B[0m", resKey, common.prettify(resource))) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 464 |                                         } | 
 | 465 |                                     } | 
 | 466 |                                 }else{ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 467 |                                     outputResources.add(String.format("Resource: %s\n\u001B[36m%s\u001B[0m", resKey, common.prettify(resource))) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 468 |                                 } | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 469 |                             } | 
| Jakub Josef | c4c4020 | 2017-04-28 12:04:24 +0200 | [diff] [blame] | 470 |                             common.debugMsg("checkResult: checking resource: ${resource}") | 
 | 471 |                             if(resource instanceof String || (resource["result"] != null && !resource["result"]) || (resource["result"] instanceof String && resource["result"] == "false")){ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 472 |                                 def prettyResource = common.prettify(resource) | 
| Jakub Josef | c4c4020 | 2017-04-28 12:04:24 +0200 | [diff] [blame] | 473 |                                 if(env["ASK_ON_ERROR"] && env["ASK_ON_ERROR"] == "true"){ | 
 | 474 |                                     timeout(time:1, unit:'HOURS') { | 
 | 475 |                                        input message: "False result on ${nodeKey} found, resource ${prettyResource}. \nDo you want to continue?" | 
 | 476 |                                     } | 
 | 477 |                                 }else{ | 
| Jakub Josef | d97d7db | 2017-05-11 19:11:53 +0200 | [diff] [blame] | 478 |                                     common.errorMsg(String.format("Resource: %s\n%s", resKey, prettyResource)) | 
| Jakub Josef | d9001df | 2017-05-11 16:45:28 +0200 | [diff] [blame] | 479 |                                     def errorMsg = "Salt state on node ${nodeKey} failed: ${prettyResource}." | 
| Jakub Josef | c4c4020 | 2017-04-28 12:04:24 +0200 | [diff] [blame] | 480 |                                     if (failOnError) { | 
 | 481 |                                         throw new Exception(errorMsg) | 
 | 482 |                                     } else { | 
 | 483 |                                         common.errorMsg(errorMsg) | 
 | 484 |                                     } | 
 | 485 |                                 } | 
 | 486 |                             } | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 487 |                         } | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 488 |                     }else if(node!=null && node!=""){ | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 489 |                         outputResources.add(String.format("Resource: %s\n\u001B[36m%s\u001B[0m", resKey, common.prettify(node))) | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 490 |                     } | 
 | 491 |                     if(printResults && !outputResources.isEmpty()){ | 
| Jakub Josef | b77c081 | 2017-03-27 14:11:01 +0200 | [diff] [blame] | 492 |                         wrap([$class: 'AnsiColorBuildWrapper']) { | 
 | 493 |                             print outputResources.stream().collect(Collectors.joining("\n")) | 
 | 494 |                         } | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 495 |                     } | 
 | 496 |                 } | 
| Jakub Josef | 52f69f7 | 2017-03-14 15:18:08 +0100 | [diff] [blame] | 497 |             } | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 498 |         }else{ | 
 | 499 |             common.errorMsg("Salt result hasn't return attribute! Result: ${result}") | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 500 |         } | 
| Jakub Josef | 52f69f7 | 2017-03-14 15:18:08 +0100 | [diff] [blame] | 501 |     }else{ | 
| Jakub Josef | a87941c | 2017-04-20 17:14:58 +0200 | [diff] [blame] | 502 |         common.errorMsg("Cannot check salt result, given result is null") | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 503 |     } | 
 | 504 | } | 
 | 505 |  | 
 | 506 | /** | 
| Jakub Josef | 7852fe1 | 2017-03-15 16:02:41 +0100 | [diff] [blame] | 507 |  * Print salt command run results in human-friendly form | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 508 |  * | 
 | 509 |  * @param result        Parsed response of Salt API | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 510 |  */ | 
| Filip Pytloun | d2f1bbe | 2017-02-27 19:03:51 +0100 | [diff] [blame] | 511 | def printSaltCommandResult(result) { | 
| Jakub Josef | 871bf15 | 2017-03-14 20:13:41 +0100 | [diff] [blame] | 512 |     def common = new com.mirantis.mk.Common() | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 513 |     if(result != null){ | 
 | 514 |         if(result['return']){ | 
 | 515 |             for (int i=0; i<result['return'].size(); i++) { | 
 | 516 |                 def entry = result['return'][i] | 
 | 517 |                 for (int j=0; j<entry.size(); j++) { | 
 | 518 |                     common.debugMsg("printSaltCommandResult: printing salt command entry: ${entry}") | 
 | 519 |                     def nodeKey = entry.keySet()[j] | 
 | 520 |                     def node=entry[nodeKey] | 
| Jakub Josef | bceaa32 | 2017-06-13 18:28:27 +0200 | [diff] [blame] | 521 |                     common.infoMsg(String.format("Node %s changes:\n%s",nodeKey, common.prettify(node))) | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 522 |                 } | 
| Jakub Josef | 8a715bf | 2017-03-14 21:39:01 +0100 | [diff] [blame] | 523 |             } | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 524 |         }else{ | 
 | 525 |             common.errorMsg("Salt result hasn't return attribute! Result: ${result}") | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 526 |         } | 
| Jakub Josef | 8a715bf | 2017-03-14 21:39:01 +0100 | [diff] [blame] | 527 |     }else{ | 
| Jakub Josef | d9afd0e | 2017-03-15 19:19:23 +0100 | [diff] [blame] | 528 |         common.errorMsg("Cannot print salt command result, given result is null") | 
| Jakub Josef | 52f69f7 | 2017-03-14 15:18:08 +0100 | [diff] [blame] | 529 |     } | 
| Jakub Josef | 79ecec3 | 2017-02-17 14:36:28 +0100 | [diff] [blame] | 530 | } | 
| Tomáš Kukrál | b12eedd | 2017-04-21 10:45:13 +0200 | [diff] [blame] | 531 |  | 
 | 532 |  | 
 | 533 | /** | 
 | 534 |  * Return content of file target | 
 | 535 |  * | 
 | 536 |  * @param master    Salt master object | 
 | 537 |  * @param target    Compound target (should target only one host) | 
 | 538 |  * @param file      File path to read (/etc/hosts for example) | 
 | 539 |  */ | 
 | 540 |  | 
 | 541 | def getFileContent(master, target, file) { | 
 | 542 |     result = cmdRun(master, target, "cat ${file}") | 
 | 543 |     return result['return'][0].values()[0] | 
 | 544 | } | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 545 |  | 
 | 546 | /** | 
 | 547 |  * Set override parameters in Salt cluster metadata | 
 | 548 |  * | 
 | 549 |  * @param master         Salt master object | 
 | 550 |  * @param salt_overrides YAML formatted string containing key: value, one per line | 
| Matthew Mosesohn | e564684 | 2017-07-19 16:54:57 +0300 | [diff] [blame] | 551 |  * @param reclass_dir    Directory where Reclass git repo is located | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 552 |  */ | 
 | 553 |  | 
| Matthew Mosesohn | e564684 | 2017-07-19 16:54:57 +0300 | [diff] [blame] | 554 | def setSaltOverrides(master, salt_overrides, reclass_dir="/srv/salt/reclass") { | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 555 |     def mcpcommon = new com.mirantis.mcp.Common() | 
| Tomáš Kukrál | f178f05 | 2017-07-11 11:31:00 +0200 | [diff] [blame] | 556 |     def common = new com.mirantis.mk.Common() | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 557 |  | 
 | 558 |     def salt_overrides_map = mcpcommon.loadYAML(salt_overrides) | 
| Tomáš Kukrál | 243cf84 | 2017-07-11 13:11:56 +0200 | [diff] [blame] | 559 |     for (entry in common.entries(salt_overrides_map)) { | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 560 |          def key = entry[0] | 
 | 561 |          def value = entry[1] | 
 | 562 |  | 
 | 563 |          common.debugMsg("Set salt override ${key}=${value}") | 
| Matthew Mosesohn | 29c9e33 | 2017-07-25 14:00:17 +0300 | [diff] [blame] | 564 |          runSaltProcessStep(master, 'I@salt:master', 'reclass.cluster_meta_set', ["${key}", "${value}"], false) | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 565 |     } | 
| Matthew Mosesohn | e564684 | 2017-07-19 16:54:57 +0300 | [diff] [blame] | 566 |     runSaltProcessStep(master, 'I@salt:master', 'cmd.run', ["git -C ${reclass_dir} update-index --skip-worktree classes/cluster/overrides.yml"]) | 
| Matthew Mosesohn | 9e88085 | 2017-07-04 21:17:53 +0300 | [diff] [blame] | 567 | } |