Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 1 | /** |
| 2 | * |
| 3 | * Run openscap xccdf evaluation on given nodes |
| 4 | * |
| 5 | * Expected parametes: |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 6 | * OPENSCAP_TEST_TYPE Type of OpenSCAP evaluation to run, either 'xccdf' or 'oval' |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 7 | * SALT_MASTER_URL Full Salt API address. |
| 8 | * SALT_MASTER_CREDENTIALS Credentials to the Salt API. |
| 9 | * |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 10 | * XCCDF_BENCHMARKS_DIR Base directory for XCCDF benchmarks (default /usr/share/xccdf-benchmarks/mirantis/) |
| 11 | * or OVAL devinitions (default /usr/share/oval-definitions/mirantis/) |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 12 | * XCCDF_BENCHMARKS List of pairs XCCDF benchmark filename and corresponding profile separated with ',' |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 13 | * these pairs are separated with semicolon |
| 14 | * (e.g. manila/openstack_manila-xccdf.xml,profilename;horizon/openstack_horizon-xccdf.xml,profile). |
| 15 | * For OVAL definitions, paths to OVAL definition files separated by semicolon, profile is ignored. |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 16 | * XCCDF_VERSION The XCCDF version (default 1.2) |
| 17 | * XCCDF_TAILORING_ID The tailoring id (default None) |
Ivan Udovichenko | 21892e6 | 2018-12-04 13:16:45 +0300 | [diff] [blame] | 18 | * XCCDF_CPE CPE dictionary or language for applicability checks (default None) |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 19 | * |
| 20 | * TARGET_SERVERS The target Salt nodes (default *) |
| 21 | * |
| 22 | * ARTIFACTORY_URL The artifactory URL |
| 23 | * ARTIFACTORY_NAMESPACE The artifactory namespace (default 'mirantis/openscap') |
| 24 | * ARTIFACTORY_REPO The artifactory repo (default 'binary-dev-local') |
| 25 | * |
| 26 | * UPLOAD_TO_DASHBOARD Boolean. Upload results to the WORP or not |
| 27 | * DASHBOARD_API_URL The WORP api base url. Mandatory if UPLOAD_TO_DASHBOARD is true |
Pavlo Shchelokovskyy | 7373b71 | 2018-12-26 13:17:32 +0000 | [diff] [blame] | 28 | * CLOUD_NAME Name of the cloud to post results to dashboard for. |
| 29 | If not specified, the internal cloud name resolved from Salt master will be used. |
| 30 | Suitable for CI-like use case. |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 31 | */ |
| 32 | |
| 33 | |
| 34 | |
| 35 | /** |
| 36 | * Upload results to the `WORP` dashboard |
| 37 | * |
| 38 | * @param apiUrl The base dashboard api url |
| 39 | * @param cloudName The cloud name (mostly, the given node's domain name) |
| 40 | * @param nodeName The node name |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 41 | * @param reportType Type of the report to create/use, either 'openscap' or 'cve' |
| 42 | * @param reportId Report Id to re-use, if empty report will be created |
| 43 | * @param results The scanning results as a json file content (string) |
| 44 | * @return reportId The Id of the report created if incoming reportId was empty, otherwise incoming reportId |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 45 | */ |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 46 | def uploadResultToDashboard(apiUrl, cloudName, nodeName, reportType, reportId, results) { |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 47 | def common = new com.mirantis.mk.Common() |
| 48 | def http = new com.mirantis.mk.Http() |
| 49 | |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 50 | // Yes, we do not care of performance and will create at least 4 requests per each result |
| 51 | def requestData = [:] |
| 52 | |
| 53 | def cloudId |
| 54 | def nodeId |
| 55 | |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 56 | def worpApi = [:] |
| 57 | worpApi["url"] = apiUrl |
| 58 | |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 59 | // Let's take a look, may be our minion is already presented on the dashboard |
| 60 | // Get available environments |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 61 | common.infoMsg("Making GET to ${worpApi.url}/environment/") |
| 62 | environments = http.restGet(worpApi, "/environment/") |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 63 | for (environment in environments) { |
| 64 | if (environment['name'] == cloudName) { |
| 65 | cloudId = environment['uuid'] |
| 66 | break |
| 67 | } |
| 68 | } |
| 69 | // Cloud wasn't presented, let's create it |
| 70 | if (! cloudId ) { |
| 71 | // Create cloud |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 72 | requestData = [:] |
| 73 | requestData['name'] = cloudName |
| 74 | common.infoMsg("Making POST to ${worpApi.url}/environment/ with ${requestData}") |
| 75 | cloudId = http.restPost(worpApi, "/environment/", requestData)['env']['uuid'] |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 76 | |
| 77 | // And the node |
| 78 | // It was done here to reduce count of requests to the api. |
| 79 | // Because if there was not cloud presented on the dashboard, then the node was not presented as well. |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 80 | requestData = [:] |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 81 | requestData['nodes'] = [nodeName] |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 82 | common.infoMsg("Making PUT to ${worpApi.url}/environment/${cloudId}/nodes/ with ${requestData}") |
| 83 | nodeId = http.restCall(worpApi, "/environment/${cloudId}/nodes/", "PUT", requestData)['uuid'] |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | if (! nodeId ) { |
| 87 | // Get available nodes in our environment |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 88 | common.infoMsg("Making GET to ${worpApi.url}/environment/${cloudId}/nodes/") |
| 89 | nodes = http.restGet(worpApi, "/environment/${cloudId}/nodes/") |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 90 | for (node in nodes) { |
| 91 | if (node['name'] == nodeName) { |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 92 | nodeId = node['uuid'] |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 93 | break |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Node wasn't presented, let's create it |
| 99 | if (! nodeId ) { |
| 100 | // Create node |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 101 | requestData = [:] |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 102 | requestData['nodes'] = [nodeName] |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 103 | common.infoMsg("Making PUT to ${worpApi.url}/environment/${cloudId}/nodes/ with ${requestData}") |
| 104 | nodeId = http.restCall(worpApi, "/environment/${cloudId}/nodes/", "PUT", requestData)['uuid'] |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 105 | } |
| 106 | |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 107 | // Create report if needed |
| 108 | if (! reportId ) { |
| 109 | requestData = [:] |
| 110 | requestData['env_uuid'] = cloudId |
| 111 | common.infoMsg("Making POST to ${worpApi.url}/reports/${reportType}/ with ${requestData}") |
| 112 | reportId = http.restPost(worpApi, "/reports/${reportType}/", requestData)['report']['uuid'] |
| 113 | } |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 114 | |
| 115 | // Upload results |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 116 | // NOTE(pas-ha) results should already be a dict with 'results' key |
| 117 | requestData = common.parseJSON(results) |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 118 | requestData['node_name'] = nodeName |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 119 | common.infoMsg("First result in results to PUT is ${requestData['results'][0]}") |
| 120 | // NOTE(pas-ha) not logging whole results to be sent, is too large and just spams the logs |
| 121 | common.infoMsg("Making PUT to ${worpApi.url}/reports/${reportType}/${reportId}/ with node name ${requestData['node_name']} and results") |
| 122 | http.restCall(worpApi, "/reports/${reportType}/${reportId}/", "PUT", requestData) |
| 123 | return reportId |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | |
| 127 | node('python') { |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 128 | def salt = new com.mirantis.mk.Salt() |
| 129 | def python = new com.mirantis.mk.Python() |
| 130 | def common = new com.mirantis.mk.Common() |
| 131 | def http = new com.mirantis.mk.Http() |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 132 | def validate = new com.mirantis.mcp.Validate() |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 133 | |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 134 | def pepperEnv = 'pepperEnv' |
| 135 | |
| 136 | def benchmarkType = OPENSCAP_TEST_TYPE ?: 'xccdf' |
| 137 | def reportType |
| 138 | def benchmarksDir |
| 139 | |
| 140 | switch (benchmarkType) { |
| 141 | case 'xccdf': |
| 142 | reportType = 'openscap'; |
| 143 | benchmarksDir = XCCDF_BENCHMARKS_DIR ?: '/usr/share/xccdf-benchmarks/mirantis/'; |
| 144 | break; |
| 145 | case 'oval': |
| 146 | reportType = 'cve'; |
| 147 | benchmarksDir = XCCDF_BENCHMARKS_DIR ?: '/usr/share/oval-definitions/mirantis/'; |
| 148 | break; |
| 149 | default: |
| 150 | throw new Exception('Unsupported value for OPENSCAP_TEST_TYPE, must be "oval" or "xccdf".') |
| 151 | } |
| 152 | // XCCDF related variables |
| 153 | def benchmarksAndProfilesArray = XCCDF_BENCHMARKS.tokenize(';') |
| 154 | def xccdfVersion = XCCDF_VERSION ?: '1.2' |
| 155 | def xccdfTailoringId = XCCDF_TAILORING_ID ?: 'None' |
Ivan Udovichenko | 21892e6 | 2018-12-04 13:16:45 +0300 | [diff] [blame] | 156 | def xccdfCPE = XCCDF_CPE ?: '' |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 157 | def targetServers = TARGET_SERVERS ?: '*' |
| 158 | |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 159 | // To have an ability to work in heavy concurrency conditions |
| 160 | def scanUUID = UUID.randomUUID().toString() |
| 161 | |
| 162 | def artifactsArchiveName = "openscap-${scanUUID}.zip" |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 163 | def resultsBaseDir = "/var/log/openscap/${scanUUID}" |
| 164 | def artifactsDir = "openscap" |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 165 | |
| 166 | def liveMinions |
| 167 | |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 168 | |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 169 | stage ('Setup virtualenv for Pepper') { |
| 170 | python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS) |
| 171 | } |
| 172 | |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 173 | stage ('Run openscap evaluation and attempt to upload the results to a dashboard') { |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 174 | liveMinions = salt.getMinions(pepperEnv, targetServers) |
| 175 | |
| 176 | if (liveMinions.isEmpty()) { |
| 177 | throw new Exception('There are no alive minions') |
| 178 | } |
| 179 | |
| 180 | common.infoMsg("Scan UUID: ${scanUUID}") |
| 181 | |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 182 | // Clean all results before proceeding with results from every minion |
| 183 | dir(artifactsDir) { |
| 184 | deleteDir() |
| 185 | } |
| 186 | |
Pavlo Shchelokovskyy | f1b99b0 | 2018-10-02 20:31:17 +0300 | [diff] [blame] | 187 | def reportId |
Pavlo Shchelokovskyy | 011495f | 2018-10-10 13:03:57 +0300 | [diff] [blame] | 188 | def lastError |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 189 | // Iterate oscap evaluation over the benchmarks |
| 190 | for (benchmark in benchmarksAndProfilesArray) { |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 191 | def (benchmarkFilePath, profileName) = benchmark.tokenize(',').collect({it.trim()}) |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 192 | |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 193 | // Remove extension from the benchmark name |
| 194 | def benchmarkPathWithoutExtension = benchmarkFilePath.replaceFirst('[.][^.]+$', '') |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 195 | |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 196 | // Get benchmark name |
| 197 | def benchmarkName = benchmarkPathWithoutExtension.tokenize('/')[-1] |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 198 | |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 199 | // And build resultsDir based on this path |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 200 | def resultsDir = "${resultsBaseDir}/${benchmarkName}" |
| 201 | if (profileName) { |
| 202 | resultsDir = "${resultsDir}/${profileName}" |
| 203 | } |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 204 | |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 205 | def benchmarkFile = "${benchmarksDir}${benchmarkFilePath}" |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 206 | |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 207 | // Evaluate the benchmark on all minions at once |
| 208 | salt.runSaltProcessStep(pepperEnv, targetServers, 'oscap.eval', [ |
Pavlo Shchelokovskyy | 319e00f | 2018-10-08 17:15:44 +0300 | [diff] [blame] | 209 | benchmarkType, benchmarkFile, "results_dir=${resultsDir}", |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 210 | "profile=${profileName}", "xccdf_version=${xccdfVersion}", |
Ivan Udovichenko | 21892e6 | 2018-12-04 13:16:45 +0300 | [diff] [blame] | 211 | "tailoring_id=${xccdfTailoringId}", "cpe=${xccdfCPE}" |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 212 | ]) |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 213 | |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 214 | salt.cmdRun(pepperEnv, targetServers, "rm -f /tmp/${scanUUID}.tar.xz; tar -cJf /tmp/${scanUUID}.tar.xz -C ${resultsBaseDir} .") |
| 215 | |
| 216 | // fetch and store results one by one |
| 217 | for (minion in liveMinions) { |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 218 | def nodeShortName = minion.tokenize('.')[0] |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 219 | def localResultsDir = "${artifactsDir}/${scanUUID}/${nodeShortName}" |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 220 | |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 221 | fileContentBase64 = validate.getFileContentEncoded(pepperEnv, minion, "/tmp/${scanUUID}.tar.xz") |
| 222 | writeFile file: "${scanUUID}.base64", text: fileContentBase64 |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 223 | |
Pavlo Shchelokovskyy | 82117e4 | 2018-10-03 19:48:56 +0300 | [diff] [blame] | 224 | sh "mkdir -p ${localResultsDir}" |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 225 | sh "base64 -d ${scanUUID}.base64 | tar -xJ --strip-components 1 --directory ${localResultsDir}" |
| 226 | sh "rm -f ${scanUUID}.base64" |
| 227 | } |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 228 | |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 229 | // Remove archives which is not needed anymore |
| 230 | salt.runSaltProcessStep(pepperEnv, targetServers, 'file.remove', "/tmp/${scanUUID}.tar.xz") |
| 231 | |
| 232 | // publish results one by one |
| 233 | for (minion in liveMinions) { |
| 234 | def nodeShortName = minion.tokenize('.')[0] |
| 235 | def benchmarkResultsDir = "${artifactsDir}/${scanUUID}/${nodeShortName}/${benchmarkName}" |
| 236 | if (profileName) { |
| 237 | benchmarkResultsDir = "${benchmarkResultsDir}/${profileName}" |
| 238 | } |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 239 | |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 240 | // Attempt to upload the scanning results to the dashboard |
| 241 | if (UPLOAD_TO_DASHBOARD.toBoolean()) { |
| 242 | if (common.validInputParam('DASHBOARD_API_URL')) { |
Pavlo Shchelokovskyy | 7373b71 | 2018-12-26 13:17:32 +0000 | [diff] [blame] | 243 | def cloudName |
| 244 | if (common.validInputParam('CLOUD_NAME')) { |
| 245 | cloudName = CLOUD_NAME |
| 246 | } else { |
| 247 | cloudName = salt.getGrain(pepperEnv, minion, 'domain')['return'][0].values()[0].values()[0] |
| 248 | } |
Pavlo Shchelokovskyy | 011495f | 2018-10-10 13:03:57 +0300 | [diff] [blame] | 249 | try { |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 250 | def nodeResults = readFile "${benchmarkResultsDir}/results.json" |
Pavlo Shchelokovskyy | 011495f | 2018-10-10 13:03:57 +0300 | [diff] [blame] | 251 | reportId = uploadResultToDashboard(DASHBOARD_API_URL, cloudName, minion, reportType, reportId, nodeResults) |
Dmitry Teselkin | 1691a2e | 2018-10-11 12:37:44 +0300 | [diff] [blame] | 252 | common.infoMsg("Report ID is ${reportId}.") |
Pavlo Shchelokovskyy | 011495f | 2018-10-10 13:03:57 +0300 | [diff] [blame] | 253 | } catch (Exception e) { |
| 254 | lastError = e |
| 255 | } |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 256 | } else { |
| 257 | throw new Exception('Uploading to the dashboard is enabled but the DASHBOARD_API_URL was not set') |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | } |
Ivan Udovichenko | d1bd28c | 2018-10-02 12:41:04 +0300 | [diff] [blame] | 262 | |
| 263 | // Prepare archive |
| 264 | sh "tar -cJf ${artifactsDir}.tar.xz ${artifactsDir}" |
| 265 | |
| 266 | // Archive the build output artifacts |
| 267 | archiveArtifacts artifacts: "*.xz" |
Pavlo Shchelokovskyy | 011495f | 2018-10-10 13:03:57 +0300 | [diff] [blame] | 268 | if (lastError) { |
| 269 | common.infoMsg('Uploading some results to the dashboard report ${reportId} failed. Raising last error.') |
| 270 | throw lastError |
| 271 | } |
Vasyl Saienko | 4e8ec64 | 2018-09-17 10:08:08 +0000 | [diff] [blame] | 272 | } |
| 273 | |
| 274 | /* // Will be implemented later |
| 275 | stage ('Attempt to upload results to an artifactory') { |
| 276 | if (common.validInputParam('ARTIFACTORY_URL')) { |
| 277 | for (minion in liveMinions) { |
| 278 | def destDir = "${artifactsDir}/${minion}" |
| 279 | def archiveName = "openscap-${scanUUID}.tar.gz" |
| 280 | def tempArchive = "/tmp/${archiveName}" |
| 281 | def destination = "${destDir}/${archiveName}" |
| 282 | |
| 283 | dir(destDir) { |
| 284 | // Archive scanning results on the remote target |
| 285 | salt.runSaltProcessStep(pepperEnv, minion, 'archive.tar', ['czf', tempArchive, resultsBaseDir]) |
| 286 | |
| 287 | // Get it content and save it |
| 288 | writeFile file: destination, text: salt.getFileContent(pepperEnv, minion, tempArchive) |
| 289 | |
| 290 | // Remove scanning results and the temp archive on the remote target |
| 291 | salt.runSaltProcessStep(pepperEnv, minion, 'file.remove', resultsBaseDir) |
| 292 | salt.runSaltProcessStep(pepperEnv, minion, 'file.remove', tempArchive) |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | def artifactory = new com.mirantis.mcp.MCPArtifactory() |
| 297 | def artifactoryName = 'mcp-ci' |
| 298 | def artifactoryRepo = ARTIFACTORY_REPO ?: 'binary-dev-local' |
| 299 | def artifactoryNamespace = ARTIFACTORY_NAMESPACE ?: 'mirantis/openscap' |
| 300 | def artifactoryServer = Artifactory.server(artifactoryName) |
| 301 | def publishInfo = true |
| 302 | def buildInfo = Artifactory.newBuildInfo() |
| 303 | def zipName = "${env.WORKSPACE}/openscap/${scanUUID}/results.zip" |
| 304 | |
| 305 | // Zip scan results |
| 306 | zip zipFile: zipName, archive: false, dir: artifactsDir |
| 307 | |
| 308 | // Mandatory and additional properties |
| 309 | def properties = artifactory.getBinaryBuildProperties([ |
| 310 | "scanUuid=${scanUUID}", |
| 311 | "project=openscap" |
| 312 | ]) |
| 313 | |
| 314 | // Build Artifactory spec object |
| 315 | def uploadSpec = """{ |
| 316 | "files": |
| 317 | [ |
| 318 | { |
| 319 | "pattern": "${zipName}", |
| 320 | "target": "${artifactoryRepo}/${artifactoryNamespace}/openscap", |
| 321 | "props": "${properties}" |
| 322 | } |
| 323 | ] |
| 324 | }""" |
| 325 | |
| 326 | // Upload artifacts to the given Artifactory |
| 327 | artifactory.uploadBinariesToArtifactory(artifactoryServer, buildInfo, uploadSpec, publishInfo) |
| 328 | |
| 329 | } else { |
| 330 | common.warningMsg('ARTIFACTORY_URL was not given, skip uploading to artifactory') |
| 331 | } |
| 332 | } |
| 333 | */ |
| 334 | |
| 335 | } |