Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 1 | /** |
| 2 | * |
Oleg Basov | 3d93f55 | 2019-03-27 01:01:20 +0100 | [diff] [blame] | 3 | * Launch validation of the cloud with Rally |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 4 | * |
| 5 | * Expected parameters: |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 6 | * |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 7 | * JOB_TIMEOUT Job timeout in hours |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 8 | * SALT_MASTER_URL URL of Salt master |
| 9 | * SALT_MASTER_CREDENTIALS Credentials to the Salt API |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 10 | * VALIDATE_PARAMS Validate job YAML params (see below) |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 11 | * |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 12 | * Rally - map with parameters for starting Rally tests |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 13 | * |
Dmitrii Kabanov | 9f3b7ed | 2017-09-29 10:47:36 -0700 | [diff] [blame] | 14 | * AVAILABILITY_ZONE The name of availability zone |
| 15 | * FLOATING_NETWORK The name of the external(floating) network |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 16 | * K8S_RALLY Use Kubernetes Rally plugin for testing K8S cluster |
| 17 | * STACKLIGHT_RALLY Use Stacklight Rally plugin for testing Stacklight |
Dmitrii Kabanov | 9f3b7ed | 2017-09-29 10:47:36 -0700 | [diff] [blame] | 18 | * RALLY_IMAGE The name of the image for Rally tests |
| 19 | * RALLY_FLAVOR The name of the flavor for Rally image |
Oleg Basov | 41c4fe7 | 2018-06-10 01:16:58 +0200 | [diff] [blame] | 20 | * RALLY_PLUGINS_REPO Git repository with Rally plugins |
| 21 | * RALLY_PLUGINS_BRANCH Git branch which will be used during the checkout |
Dmitrii Kabanov | b2f60ee | 2017-11-10 00:31:50 -0800 | [diff] [blame] | 22 | * RALLY_CONFIG_REPO Git repository with files for Rally |
| 23 | * RALLY_CONFIG_BRANCH Git branch which will be used during the checkout |
Sergey Galkin | 8991e82 | 2017-11-29 19:10:46 +0400 | [diff] [blame] | 24 | * RALLY_SCENARIOS Path to file or directory with rally scenarios |
Oleg Basov | bf86032 | 2018-09-04 20:54:36 +0200 | [diff] [blame] | 25 | * RALLY_SL_SCENARIOS Path to file or directory with stacklight rally scenarios |
Sergey Galkin | 8991e82 | 2017-11-29 19:10:46 +0400 | [diff] [blame] | 26 | * RALLY_TASK_ARGS_FILE Path to file with rally tests arguments |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 27 | * RALLY_DB_CONN_STRING Rally-compliant DB connection string for long-term storing |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 28 | * results to external DB |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 29 | * RALLY_TAGS List of tags for marking Rally tasks. Can be used when |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 30 | * generating Rally trends based on particular group of tasks |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 31 | * RALLY_TRENDS If enabled, generate Rally trends report. Requires external DB |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 32 | * connection string to be set. If RALLY_TAGS was set, trends will |
| 33 | * be generated based on finished tasks with these tags, otherwise |
| 34 | * on all the finished tasks available in DB |
mkraynov | da6b698 | 2018-08-06 17:48:24 +0400 | [diff] [blame] | 35 | * SKIP_LIST List of the Rally scenarios which should be skipped |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 36 | * |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 37 | * PARALLEL_PERFORMANCE If enabled, run Rally tests separately in parallel for each sub directory found |
| 38 | * inside RALLY_SCENARIOS and RALLY_SL_SCENARIOS (if STACKLIGHT_RALLY is enabled) |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 39 | */ |
| 40 | |
| 41 | common = new com.mirantis.mk.Common() |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 42 | validate = new com.mirantis.mcp.Validate() |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 43 | salt = new com.mirantis.mk.Salt() |
| 44 | salt_testing = new com.mirantis.mk.SaltModelTesting() |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 45 | |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 46 | def VALIDATE_PARAMS = readYaml(text: env.getProperty('VALIDATE_PARAMS')) ?: [:] |
| 47 | if (! VALIDATE_PARAMS) { |
| 48 | throw new Exception("VALIDATE_PARAMS yaml is empty.") |
| 49 | } |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 50 | def TEST_IMAGE = env.getProperty('TEST_IMAGE') ?: 'xrally-openstack:1.4.0' |
| 51 | def JOB_TIMEOUT = env.getProperty('JOB_TIMEOUT').toInteger() ?: 12 |
| 52 | def SLAVE_NODE = env.getProperty('SLAVE_NODE') ?: 'docker' |
| 53 | def rally = VALIDATE_PARAMS.get('rally') ?: [:] |
| 54 | def scenariosRepo = rally.get('RALLY_CONFIG_REPO') ?: 'https://review.gerrithub.io/Mirantis/scale-scenarios' |
| 55 | def scenariosBranch = rally.get('RALLY_CONFIG_BRANCH') ?: 'master' |
| 56 | def pluginsRepo = rally.get('RALLY_PLUGINS_REPO') ?: 'https://github.com/Mirantis/rally-plugins' |
| 57 | def pluginsBranch = rally.get('RALLY_PLUGINS_BRANCH') ?: 'master' |
| 58 | def tags = rally.get('RALLY_TAGS') ?: [] |
Oleg Basov | d4fa386 | 2019-03-05 21:49:12 +0100 | [diff] [blame] | 59 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 60 | // contrainer working dir vars |
| 61 | def rallyWorkdir = '/home/rally' |
| 62 | def rallyPluginsDir = "${rallyWorkdir}/rally-plugins" |
| 63 | def rallyScenariosDir = "${rallyWorkdir}/rally-scenarios" |
| 64 | def rallyResultsDir = "${rallyWorkdir}/test_results" |
| 65 | def rallySecrets = "${rallyWorkdir}/secrets" |
Oleg Basov | 3d93f55 | 2019-03-27 01:01:20 +0100 | [diff] [blame] | 66 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 67 | // env vars |
| 68 | def env_vars = [] |
| 69 | def platform = [ |
| 70 | type: 'unknown', |
| 71 | stacklight: [enabled: false, grafanaPass: ''], |
| 72 | ] |
| 73 | def cmp_count |
| 74 | |
| 75 | // test results vars |
| 76 | def testResult |
| 77 | def tasksParallel = [:] |
| 78 | def parallelResults = [:] |
| 79 | def configRun = [:] |
| 80 | |
| 81 | timeout(time: JOB_TIMEOUT, unit: 'HOURS') { |
| 82 | node (SLAVE_NODE) { |
| 83 | |
| 84 | // local dir vars |
| 85 | def workDir = "${env.WORKSPACE}/rally" |
| 86 | def pluginsDir = "${workDir}/rally-plugins" |
| 87 | def scenariosDir = "${workDir}/rally-scenarios" |
| 88 | def secrets = "${workDir}/secrets" |
| 89 | def artifacts = "${workDir}/validation_artifacts" |
| 90 | |
| 91 | stage('Configure env') { |
| 92 | |
| 93 | def master = salt.connection(SALT_MASTER_URL, SALT_MASTER_CREDENTIALS) |
| 94 | |
| 95 | // create local directories |
| 96 | sh "rm -rf ${workDir} || true" |
| 97 | sh "mkdir -p ${artifacts} ${secrets}" |
| 98 | writeFile file: "${workDir}/entrypoint.sh", text: '''#!/bin/bash |
| 99 | set -xe |
| 100 | exec "$@" |
| 101 | ''' |
| 102 | sh "chmod 755 ${workDir}/entrypoint.sh" |
| 103 | |
| 104 | // clone repo with Rally plugins and checkout refs/branch |
| 105 | checkout([ |
| 106 | $class : 'GitSCM', |
| 107 | branches : [[name: 'FETCH_HEAD']], |
| 108 | extensions : [[$class: 'RelativeTargetDirectory', relativeTargetDir: pluginsDir]], |
| 109 | userRemoteConfigs: [[url: pluginsRepo, refspec: pluginsBranch]], |
| 110 | ]) |
| 111 | |
| 112 | // clone scenarios repo and switch branch / fetch refspecs |
| 113 | checkout([ |
| 114 | $class : 'GitSCM', |
| 115 | branches : [[name: 'FETCH_HEAD']], |
| 116 | extensions : [[$class: 'RelativeTargetDirectory', relativeTargetDir: scenariosDir]], |
| 117 | userRemoteConfigs: [[url: scenariosRepo, refspec: scenariosBranch]], |
| 118 | ]) |
| 119 | |
| 120 | // get number of computes in the cluster |
| 121 | platform['cluster_name'] = salt.getPillar( |
| 122 | master, 'I@salt:master', '_param:cluster_name' |
| 123 | )['return'][0].values()[0] |
| 124 | def rcs_str_node = salt.getPillar( |
| 125 | master, 'I@salt:master', 'reclass:storage:node' |
| 126 | )['return'][0].values()[0] |
| 127 | |
| 128 | // set up Openstack env variables |
| 129 | if (rally.get('K8S_RALLY').toBoolean() == false) { |
| 130 | |
| 131 | platform['type'] = 'openstack' |
| 132 | platform['cmp_count'] = rcs_str_node.openstack_compute_rack01['repeat']['count'] |
| 133 | def rally_variables = [ |
| 134 | "floating_network=${rally.FLOATING_NETWORK}", |
| 135 | "rally_image=${rally.RALLY_IMAGE}", |
| 136 | "rally_flavor=${rally.RALLY_FLAVOR}", |
| 137 | "availability_zone=${rally.AVAILABILITY_ZONE}", |
| 138 | ] |
| 139 | |
| 140 | env_vars = validate._get_keystone_creds_v3(master) |
| 141 | if (!env_vars) { |
| 142 | env_vars = validate._get_keystone_creds_v2(master) |
| 143 | } |
| 144 | env_vars = env_vars + rally_variables |
| 145 | |
| 146 | } else { |
| 147 | // set up Kubernetes env variables get required secrets |
| 148 | platform['type'] = 'k8s' |
| 149 | platform['cmp_count'] = rcs_str_node.kubernetes_compute_rack01['repeat']['count'] |
| 150 | |
| 151 | def kubernetes = salt.getPillar( |
| 152 | master, 'I@kubernetes:master and *01*', 'kubernetes:master' |
| 153 | )['return'][0].values()[0] |
| 154 | |
| 155 | env_vars = [ |
| 156 | "KUBERNETES_HOST=http://${kubernetes.apiserver.vip_address}" + |
| 157 | ":${kubernetes.apiserver.insecure_port}", |
| 158 | "KUBERNETES_CERT_AUTH=${rallySecrets}/k8s-ca.crt", |
| 159 | "KUBERNETES_CLIENT_KEY=${rallySecrets}/k8s-client.key", |
| 160 | "KUBERNETES_CLIENT_CERT=${rallySecrets}/k8s-client.crt", |
| 161 | ] |
| 162 | |
| 163 | // get K8S certificates to manage cluster |
| 164 | def k8s_ca = salt.getFileContent( |
| 165 | master, 'I@kubernetes:master and *01*', '/etc/kubernetes/ssl/ca-kubernetes.crt' |
| 166 | ) |
| 167 | def k8s_client_key = salt.getFileContent( |
| 168 | master, 'I@kubernetes:master and *01*', '/etc/kubernetes/ssl/kubelet-client.key' |
| 169 | ) |
| 170 | def k8s_client_crt = salt.getFileContent( |
| 171 | master, 'I@kubernetes:master and *01*', '/etc/kubernetes/ssl/kubelet-client.crt' |
| 172 | ) |
| 173 | writeFile file: "${secrets}/k8s-ca.crt", text: k8s_ca |
| 174 | writeFile file: "${secrets}/k8s-client.key", text: k8s_client_key |
| 175 | writeFile file: "${secrets}/k8s-client.crt", text: k8s_client_crt |
| 176 | |
Tetiana Korchak | efa4f78 | 2017-08-25 10:22:29 -0700 | [diff] [blame] | 177 | } |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 178 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 179 | // get Stacklight data |
| 180 | if (rally.STACKLIGHT_RALLY.toBoolean() == true) { |
| 181 | platform['stacklight']['enabled'] = true |
| 182 | |
| 183 | def grafana = salt.getPillar( |
| 184 | master, 'I@grafana:client', 'grafana:client:server' |
| 185 | )['return'][0].values()[0] |
| 186 | |
| 187 | platform['stacklight']['grafanaPass'] = grafana['password'] |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 188 | } |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 189 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 190 | if (! rally.PARALLEL_PERFORMANCE.toBoolean()) { |
Dmitrii Kabanov | 6b9343e | 2017-08-30 15:30:21 -0700 | [diff] [blame] | 191 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 192 | // Define map with docker commands |
| 193 | def commands = validate.runRallyTests( |
| 194 | platform, rally.RALLY_SCENARIOS, |
Oleg Basov | 3d93f55 | 2019-03-27 01:01:20 +0100 | [diff] [blame] | 195 | rally.RALLY_SL_SCENARIOS, rally.RALLY_TASK_ARGS_FILE, |
| 196 | rally.RALLY_DB_CONN_STRING, tags, |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 197 | rally.RALLY_TRENDS.toBoolean(), rally.SKIP_LIST |
Oleg Basov | 3d93f55 | 2019-03-27 01:01:20 +0100 | [diff] [blame] | 198 | ) |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 199 | def commands_list = commands.collectEntries{ [ (it.key) : { sh("${it.value}") } ] } |
Dmitrii Kabanov | a67e5a5 | 2017-08-14 16:31:11 -0700 | [diff] [blame] | 200 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 201 | configRun = [ |
| 202 | 'image': TEST_IMAGE, |
| 203 | 'baseRepoPreConfig': false, |
| 204 | 'dockerMaxCpus': 2, |
| 205 | 'dockerHostname': 'localhost', |
| 206 | 'dockerExtraOpts': [ |
| 207 | "--network=host", |
| 208 | "--entrypoint=/entrypoint.sh", |
| 209 | "-w ${rallyWorkdir}", |
| 210 | "-v ${workDir}/entrypoint.sh:/entrypoint.sh", |
| 211 | "-v ${pluginsDir}/:${rallyPluginsDir}", |
| 212 | "-v ${scenariosDir}/:${rallyScenariosDir}", |
| 213 | "-v ${artifacts}/:${rallyResultsDir}", |
| 214 | "-v ${secrets}/:${rallySecrets}", |
| 215 | ], |
| 216 | 'envOpts' : env_vars, |
| 217 | 'runCommands' : commands_list, |
| 218 | ] |
| 219 | common.infoMsg('Docker config:') |
| 220 | println configRun |
| 221 | common.infoMsg('Docker commands list:') |
| 222 | println commands |
Oleg Basov | 3d93f55 | 2019-03-27 01:01:20 +0100 | [diff] [blame] | 223 | |
Oleg Basov | 382613a | 2019-04-02 19:01:15 +0200 | [diff] [blame^] | 224 | } else { |
| 225 | |
| 226 | // Perform parallel testing of the components with Rally |
| 227 | def components = [ |
| 228 | Common: [], |
| 229 | Stacklight: [], |
| 230 | ] |
| 231 | |
| 232 | // get list of directories inside scenarios path |
| 233 | def scenPath = "${scenariosDir}/${rally.RALLY_SCENARIOS}" |
| 234 | def mainComponents = sh( |
| 235 | script: "find ${scenPath} -maxdepth 1 -mindepth 1 -type d -exec basename {} \\;", |
| 236 | returnStdout: true, |
| 237 | ).trim() |
| 238 | if (! mainComponents) { |
| 239 | error( |
| 240 | "No directories found inside RALLY_SCENARIOS ${rally.RALLY_SCENARIOS}\n" + |
| 241 | "Either set PARALLEL_PERFORMANCE=false or populate ${rally.RALLY_SCENARIOS} " + |
| 242 | "with component directories which include corresponding scenarios" |
| 243 | ) |
| 244 | } |
| 245 | components['Common'].addAll(mainComponents.split('\n')) |
| 246 | common.infoMsg( "Adding for parallel execution sub dirs found in " + |
| 247 | "RALLY_SCENARIOS (${rally.RALLY_SCENARIOS}):" |
| 248 | ) |
| 249 | print mainComponents |
| 250 | |
| 251 | if (rally.STACKLIGHT_RALLY.toBoolean() == true) { |
| 252 | def slScenPath = "${scenariosDir}/${rally.RALLY_SL_SCENARIOS}" |
| 253 | def slComponents = sh( |
| 254 | script: "find ${slScenPath} -maxdepth 1 -mindepth 1 -type d -exec basename {} \\;", |
| 255 | returnStdout: true, |
| 256 | ).trim() |
| 257 | if (! slComponents) { |
| 258 | error( |
| 259 | "No directories found inside RALLY_SCENARIOS ${rally.RALLY_SL_SCENARIOS}\n" + |
| 260 | "Either set PARALLEL_PERFORMANCE=false or populate ${rally.RALLY_SL_SCENARIOS} " + |
| 261 | "with component directories which include corresponding scenarios" |
| 262 | ) |
| 263 | } |
| 264 | components['Stacklight'].addAll(slComponents.split('\n')) |
| 265 | common.infoMsg( "Adding for parallel execution sub dirs found in " + |
| 266 | "RALLY_SL_SCENARIOS (${rally.RALLY_SL_SCENARIOS}):" |
| 267 | ) |
| 268 | print slComponents |
| 269 | } |
| 270 | |
| 271 | // build up a map with tasks for parallel execution |
| 272 | def allComponents = components.values().flatten() |
| 273 | for (int i=0; i < allComponents.size(); i++) { |
| 274 | // randomize run so we don't bump each other at the startup |
| 275 | // also we need to let first thread create rally deployment |
| 276 | // so all the rest rally threads can use it after |
| 277 | def sleepSeconds = 15 * i |
| 278 | |
| 279 | def task = allComponents[i] |
| 280 | def task_name = 'rally_' + task |
| 281 | def curComponent = components.find { task in it.value }.key |
| 282 | // inherit platform common data |
| 283 | def curPlatform = platform |
| 284 | |
| 285 | // setup scenarios and stacklight switch per component |
| 286 | def commonScens = "${rally.RALLY_SCENARIOS}/${task}" |
| 287 | def stacklightScens = "${rally.RALLY_SL_SCENARIOS}/${task}" |
| 288 | |
| 289 | switch (curComponent) { |
| 290 | case 'Common': |
| 291 | stacklightScens = '' |
| 292 | curPlatform['stacklight']['enabled'] = false |
| 293 | break |
| 294 | case 'Stacklight': |
| 295 | commonScens = '' |
| 296 | curPlatform['stacklight']['enabled'] = true |
| 297 | break |
| 298 | } |
| 299 | |
| 300 | def curCommands = validate.runRallyTests( |
| 301 | curPlatform, commonScens, |
| 302 | stacklightScens, rally.RALLY_TASK_ARGS_FILE, |
| 303 | rally.RALLY_DB_CONN_STRING, tags, |
| 304 | rally.RALLY_TRENDS.toBoolean(), rally.SKIP_LIST |
| 305 | ) |
| 306 | |
| 307 | // copy required files for the current task |
| 308 | def taskWorkDir = "${env.WORKSPACE}/rally_" + task |
| 309 | def taskPluginsDir = "${taskWorkDir}/rally-plugins" |
| 310 | def taskScenariosDir = "${taskWorkDir}/rally-scenarios" |
| 311 | def taskArtifacts = "${taskWorkDir}/validation_artifacts" |
| 312 | def taskSecrets = "${taskWorkDir}/secrets" |
| 313 | sh "rm -rf ${taskWorkDir} || true" |
| 314 | sh "cp -ra ${workDir} ${taskWorkDir}" |
| 315 | |
| 316 | def curCommandsList = curCommands.collectEntries{ [ (it.key) : { sh("${it.value}") } ] } |
| 317 | def curConfigRun = [ |
| 318 | 'image': TEST_IMAGE, |
| 319 | 'baseRepoPreConfig': false, |
| 320 | 'dockerMaxCpus': 2, |
| 321 | 'dockerHostname': 'localhost', |
| 322 | 'dockerExtraOpts': [ |
| 323 | "--network=host", |
| 324 | "--entrypoint=/entrypoint.sh", |
| 325 | "-w ${rallyWorkdir}", |
| 326 | "-v ${taskWorkDir}/entrypoint.sh:/entrypoint.sh", |
| 327 | "-v ${taskPluginsDir}/:${rallyPluginsDir}", |
| 328 | "-v ${taskScenariosDir}/:${rallyScenariosDir}", |
| 329 | "-v ${taskArtifacts}/:${rallyResultsDir}", |
| 330 | "-v ${taskSecrets}/:${rallySecrets}", |
| 331 | ], |
| 332 | 'envOpts' : env_vars, |
| 333 | 'runCommands' : curCommandsList, |
| 334 | ] |
| 335 | |
| 336 | tasksParallel['rally_' + task] = { |
| 337 | sleep sleepSeconds |
| 338 | common.infoMsg("Docker config for task $task") |
| 339 | println curConfigRun |
| 340 | common.infoMsg("Docker commands list for task $task") |
| 341 | println curCommands |
| 342 | parallelResults[task_name] = salt_testing.setupDockerAndTest(curConfigRun) |
| 343 | } |
| 344 | } |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | stage('Run Rally tests') { |
| 349 | |
| 350 | def dockerStatuses = [:] |
| 351 | |
| 352 | // start tests in Docker |
| 353 | if (! rally.PARALLEL_PERFORMANCE.toBoolean()) { |
| 354 | testResult = salt_testing.setupDockerAndTest(configRun) |
| 355 | dockerStatuses['rally'] = (testResult) ? 'OK' : 'FAILED' |
| 356 | } else { |
| 357 | common.infoMsg('Jobs to run in threads: ' + tasksParallel.keySet().join(' ')) |
| 358 | parallel tasksParallel |
| 359 | parallelResults.each { task -> |
| 360 | dockerStatuses[task.key] = (task.value) ? 'OK' : 'FAILED' |
| 361 | } |
| 362 | } |
| 363 | // safely archiving all possible results |
| 364 | dockerStatuses.each { task -> |
| 365 | print "Collecting results for ${task.key} (docker status = '${task.value}')" |
| 366 | try { |
| 367 | archiveArtifacts artifacts: "${task.key}/validation_artifacts/*" |
| 368 | } catch (Throwable e) { |
| 369 | print 'failed to get artifacts' |
| 370 | } |
| 371 | } |
| 372 | // setting final job status |
| 373 | def failed = dockerStatuses.findAll { it.value == 'FAILED' } |
| 374 | if (failed.size() == dockerStatuses.size()) { |
| 375 | currentBuild.result = 'FAILURE' |
| 376 | } else if (dockerStatuses.find { it.value != 'OK' }) { |
| 377 | currentBuild.result = 'UNSTABLE' |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | stage('Clean env') { |
| 382 | // remove secrets |
| 383 | sh 'find ./ -type d -name secrets -exec rm -rf \\\"{}\\\" \\; || true' |
Tetiana Korchak | efa4f78 | 2017-08-25 10:22:29 -0700 | [diff] [blame] | 384 | } |
Petr Lomakin | e700ffd | 2017-08-01 10:53:15 -0700 | [diff] [blame] | 385 | } |
| 386 | } |