blob: 7dfe3127783e347fa23428450c0c35d0e7058ee3 [file] [log] [blame]
Richard Felkl26cae4d2017-12-19 00:19:16 +01001/**
2 *
3 * Update Salt environment pipeline
4 *
5 * Expected parameters:
6 * SALT_MASTER_URL Salt API server location
7 * SALT_MASTER_CREDENTIALS Credentials to the Salt API
azvyagintsev6dac3802018-11-09 15:11:30 +02008 * TARGET_MCP_VERSION Version of MCP to upgrade to
Richard Felkl0e80d892018-06-20 13:44:54 +02009 * UPGRADE_SALTSTACK Upgrade SaltStack packages to new version.
Richard Felkl970e0082018-06-12 18:00:51 +020010 * UPDATE_CLUSTER_MODEL Update MCP version parameter in cluster model
11 * UPDATE_PIPELINES Update pipeline repositories on Gerrit
Richard Felkl26cae4d2017-12-19 00:19:16 +010012 * UPDATE_LOCAL_REPOS Update local repositories
13 */
14
15// Load shared libs
Richard Felkl5f7fdaf2018-02-15 15:38:31 +010016salt = new com.mirantis.mk.Salt()
17common = new com.mirantis.mk.Common()
18python = new com.mirantis.mk.Python()
Richard Felkl970e0082018-06-12 18:00:51 +020019jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
Richard Felkl5f7fdaf2018-02-15 15:38:31 +010020venvPepper = "venvPepper"
Richard Felkl0e80d892018-06-20 13:44:54 +020021workspace = ""
Richard Felkl5f7fdaf2018-02-15 15:38:31 +010022
azvyagintsev6dac3802018-11-09 15:11:30 +020023def triggerMirrorJob(jobName) {
Richard Felkl970e0082018-06-12 18:00:51 +020024 params = jenkinsUtils.getJobParameters(jobName)
25 build job: jobName, parameters: [
26 [$class: 'StringParameterValue', name: 'BRANCHES', value: params.get("BRANCHES")],
27 [$class: 'StringParameterValue', name: 'CREDENTIALS_ID', value: params.get("CREDENTIALS_ID")],
28 [$class: 'StringParameterValue', name: 'SOURCE_URL', value: params.get("SOURCE_URL")],
29 [$class: 'StringParameterValue', name: 'TARGET_URL', value: params.get("TARGET_URL")]
30 ]
31}
32
azvyagintsev6dac3802018-11-09 15:11:30 +020033def updateSaltStack(target, pkgs) {
34 try {
Richard Felkl0e80d892018-06-20 13:44:54 +020035 salt.runSaltProcessStep(venvPepper, target, 'pkg.install', ["force_yes=True", "pkgs='$pkgs'"], null, true, 5)
azvyagintsev6dac3802018-11-09 15:11:30 +020036 } catch (Exception ex) {
37 }
Richard Felkl0e80d892018-06-20 13:44:54 +020038
azvyagintsev6dac3802018-11-09 15:11:30 +020039 common.retry(20, 60) {
Richard Felkl0e80d892018-06-20 13:44:54 +020040 salt.minionsReachable(venvPepper, 'I@salt:master', '*')
41 def running = salt.runSaltProcessStep(venvPepper, target, 'saltutil.running', [], null, true, 5)
azvyagintsev6dac3802018-11-09 15:11:30 +020042 for (value in running.get("return")[0].values()) {
43 if (value != []) {
Richard Felkl0e80d892018-06-20 13:44:54 +020044 throw new Exception("Not all salt-minions are ready for execution")
45 }
46 }
47 }
48
49 def saltVersion = salt.getPillar(venvPepper, 'I@salt:master', "_param:salt_version").get("return")[0].values()[0]
Richard Felklf23257e2018-08-06 09:24:23 +020050 def saltMinionVersions = salt.cmdRun(venvPepper, target, "apt-cache policy salt-common | awk '/Installed/ && /$saltVersion/'").get("return")
Richard Felkl0e80d892018-06-20 13:44:54 +020051 def saltMinionVersion = ""
52
azvyagintsev6dac3802018-11-09 15:11:30 +020053 for (minion in saltMinionVersions[0].keySet()) {
54 saltMinionVersion = saltMinionVersions[0].get(minion).replace("Salt command execution success", "").trim()
55 if (saltMinionVersion == "") {
Richard Felkl0e80d892018-06-20 13:44:54 +020056 error("Installed version of Salt on $minion doesn't match specified version in the model.")
57 }
58 }
59}
60
azvyagintsev6dac3802018-11-09 15:11:30 +020061def archiveReclassInventory(filename) {
Richard Felkl0e80d892018-06-20 13:44:54 +020062 def ret = salt.cmdRun(venvPepper, 'I@salt:master', "reclass -i", true, null, false)
63 def reclassInv = ret.values()[0]
64 writeFile file: filename, text: reclassInv.toString()
65 archiveArtifacts artifacts: "$filename"
66}
67
Martin Polreich965c9032018-08-09 16:33:57 +020068def pipelineTimeout = 12
69if (common.validInputParam('PIPELINE_TIMEOUT') && PIPELINE_TIMEOUT.isInteger()) {
70 pipelineTimeout = "${PIPELINE_TIMEOUT}".toInteger()
71}
72
73timeout(time: pipelineTimeout, unit: 'HOURS') {
Jakub Josefa63f9862018-01-11 17:58:38 +010074 node("python") {
75 try {
Richard Felkl0e80d892018-06-20 13:44:54 +020076 workspace = common.getWorkspace()
azvyagintsev6dac3802018-11-09 15:11:30 +020077 if (env.TARGET_MCP_VERSION == "") {
78 error("You must specify MCP version in TARGET_MCP_VERSION variable ")
79 }
80 def gitTargetMcpVersion = env.TARGET_MCP_VERSION
81 if (env.TARGET_MCP_VERSION == "testing") {
82 gitTargetMcpVersion = "master"
83 }
Jakub Josefa63f9862018-01-11 17:58:38 +010084 python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Richard Felkl26cae4d2017-12-19 00:19:16 +010085
azvyagintsev6dac3802018-11-09 15:11:30 +020086 stage("Update Reclass") {
Richard Felkl970e0082018-06-12 18:00:51 +020087 def cluster_name = salt.getPillar(venvPepper, 'I@salt:master', "_param:cluster_name").get("return")[0].values()[0]
azvyagintsev6dac3802018-11-09 15:11:30 +020088 try {
Sergey382581a2018-10-25 12:22:26 +040089 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/ && git diff-index --quiet HEAD --")
Richard Felkl970e0082018-06-12 18:00:51 +020090 }
azvyagintsev6dac3802018-11-09 15:11:30 +020091 catch (Exception ex) {
Sergey382581a2018-10-25 12:22:26 +040092 error("You have uncommited changes in your Reclass cluster model repository. Please commit or reset them and rerun the pipeline.")
Richard Felkl970e0082018-06-12 18:00:51 +020093 }
azvyagintsev6dac3802018-11-09 15:11:30 +020094 if (UPDATE_CLUSTER_MODEL.toBoolean()) {
95 common.infoMsg('Perform: UPDATE_CLUSTER_MODEL')
Sergey382581a2018-10-25 12:22:26 +040096 def dateTime = common.getDatetime()
97 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && " +
azvyagintsev6dac3802018-11-09 15:11:30 +020098 "grep -r --exclude-dir=aptly -l 'mcp_version: .*' * | xargs sed -i 's/mcp_version: .*/mcp_version: \"$env.TARGET_MCP_VERSION\"/g'")
99 // Do the same, for deprecated variable-duplicate
100 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && " +
101 "grep -r --exclude-dir=aptly -l 'apt_mk_version: .*' * | xargs sed -i 's/apt_mk_version: .*/apt_mk_version: \"$env.TARGET_MCP_VERSION\"/g'")
102 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git checkout $gitTargetMcpVersion")
Sergey382581a2018-10-25 12:22:26 +0400103 // Add new defaults
104 common.infoMsg("Add new defaults")
105 salt.cmdRun(venvPepper, 'I@salt:master', "grep '^- system.defaults\$' /srv/salt/reclass/classes/cluster/$cluster_name/infra/init.yml || " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200106 "sed -i 's/^classes:/classes:\\n- system.defaults/' /srv/salt/reclass/classes/cluster/$cluster_name/infra/init.yml")
Sergey382581a2018-10-25 12:22:26 +0400107 common.infoMsg("The following changes were made to the cluster model and will be commited. " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200108 "Please consider if you want to push them to the remote repository or not. You have to do this manually when the run is finished.")
Sergey382581a2018-10-25 12:22:26 +0400109 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git diff")
110 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git status && " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200111 "git add -u && git commit --allow-empty -m 'Cluster model update to the release $env.TARGET_MCP_VERSION on $dateTime'")
Sergey382581a2018-10-25 12:22:26 +0400112 }
Sergey1b81c062018-10-16 17:10:21 +0400113 salt.enforceState(venvPepper, 'I@salt:master', 'reclass.storage', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100114 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100115
azvyagintsev6dac3802018-11-09 15:11:30 +0200116 if (UPDATE_LOCAL_REPOS.toBoolean()) {
Sergey1b81c062018-10-16 17:10:21 +0400117 def cluster_name = salt.getPillar(venvPepper, 'I@salt:master', "_param:cluster_name").get("return")[0].values()[0]
azvyagintsev6dac3802018-11-09 15:11:30 +0200118 stage("Update local repos") {
Jakub Josefa63f9862018-01-11 17:58:38 +0100119 common.infoMsg("Updating local repositories")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700120
Sergey1b81c062018-10-16 17:10:21 +0400121 def engine = salt.getPillar(venvPepper, 'I@aptly:publisher', "aptly:publisher:source:engine")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700122 runningOnDocker = engine.get("return")[0].containsValue("docker")
123
124 if (runningOnDocker) {
125 common.infoMsg("Aptly is running as Docker container")
azvyagintsev6dac3802018-11-09 15:11:30 +0200126 } else {
Sam Stoelingaaab79702018-04-09 18:49:39 -0700127 common.infoMsg("Aptly isn't running as Docker container. Going to use aptly user for executing aptly commands")
128 }
129
azvyagintsev6dac3802018-11-09 15:11:30 +0200130 if (runningOnDocker) {
Sergey1b81c062018-10-16 17:10:21 +0400131 salt.cmdRun(venvPepper, 'I@aptly:publisher', "aptly mirror list --raw | grep -E '*' | xargs -n 1 aptly mirror drop -force", true, null, true)
azvyagintsev6dac3802018-11-09 15:11:30 +0200132 } else {
133 salt.cmdRun(venvPepper, 'I@aptly:publisher', "aptly mirror list --raw | grep -E '*' | xargs -n 1 aptly mirror drop -force", true, null, true, ['runas=aptly'])
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100134 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100135
Sergey1b81c062018-10-16 17:10:21 +0400136 salt.enforceState(venvPepper, 'I@aptly:publisher', 'aptly', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100137
azvyagintsev6dac3802018-11-09 15:11:30 +0200138 if (runningOnDocker) {
Sergey1b81c062018-10-16 17:10:21 +0400139 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv"], null, true)
140 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_publish_update.sh', "args=-frv -u http://10.99.0.1:8080"], null, true)
azvyagintsev6dac3802018-11-09 15:11:30 +0200141 } else {
Sergey1b81c062018-10-16 17:10:21 +0400142 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv", 'runas=aptly'], null, true)
143 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_publish_update.sh', "args=-afrv", 'runas=aptly'], null, true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100144 }
Richard Felkl79d7df12018-01-05 16:40:11 +0100145
Sergey1b81c062018-10-16 17:10:21 +0400146 salt.enforceState(venvPepper, 'I@aptly:publisher', 'docker.client.registry', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100147
Sergey1b81c062018-10-16 17:10:21 +0400148 salt.enforceState(venvPepper, 'I@aptly:publisher', 'debmirror', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100149
Sergey1b81c062018-10-16 17:10:21 +0400150 salt.enforceState(venvPepper, 'I@aptly:publisher', 'git.server', true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100151
Sergey1b81c062018-10-16 17:10:21 +0400152 salt.enforceState(venvPepper, 'I@aptly:publisher', 'linux.system.file', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100153 }
154 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100155
azvyagintsev6dac3802018-11-09 15:11:30 +0200156 stage("Update Drivetrain") {
157 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$env.TARGET_MCP_VERSION/4' /etc/apt/sources.list.d/mcp_salt.list")
Richard Felkl970e0082018-06-12 18:00:51 +0200158 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get -o Dir::Etc::sourcelist='/etc/apt/sources.list.d/mcp_salt.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update")
Sergey1b81c062018-10-16 17:10:21 +0400159 // Workaround for PROD-22108
160 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get purge -y salt-formula-octavia && " +
azvyagintsev6dac3802018-11-09 15:11:30 +0200161 "apt-get install -y salt-formula-octavia")
Sergey1b81c062018-10-16 17:10:21 +0400162 // End workaround for PROD-22108
Richard Felkl970e0082018-06-12 18:00:51 +0200163 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades salt-formula-*")
Richard Felkl0e80d892018-06-20 13:44:54 +0200164
165 def inventoryBeforeFilename = "reclass-inventory-before.out"
166 def inventoryAfterFilename = "reclass-inventory-after.out"
167
168 archiveReclassInventory(inventoryBeforeFilename)
169
azvyagintsev6dac3802018-11-09 15:11:30 +0200170 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$env.TARGET_MCP_VERSION/4' /etc/apt/sources.list.d/mcp_extra.list")
Richard Felkl0e80d892018-06-20 13:44:54 +0200171 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get -o Dir::Etc::sourcelist='/etc/apt/sources.list.d/mcp_extra.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update")
172 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades reclass")
173
Richard Felkl970e0082018-06-12 18:00:51 +0200174 salt.fullRefresh(venvPepper, 'I@salt:master')
Jakub Josefa63f9862018-01-11 17:58:38 +0100175
azvyagintsev6dac3802018-11-09 15:11:30 +0200176 try {
Richard Felkl970e0082018-06-12 18:00:51 +0200177 salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
178 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200179 catch (Exception ex) {
Richard Felkl970e0082018-06-12 18:00:51 +0200180 error("Reclass fails rendering. Pay attention to your cluster model.")
181 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100182
Richard Felkl970e0082018-06-12 18:00:51 +0200183 salt.fullRefresh(venvPepper, '*')
184
azvyagintsev6dac3802018-11-09 15:11:30 +0200185 try {
Richard Felkl970e0082018-06-12 18:00:51 +0200186 salt.cmdRun(venvPepper, 'I@salt:master', "reclass-salt --top")
187 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200188 catch (Exception ex) {
Richard Felkl970e0082018-06-12 18:00:51 +0200189 error("Reclass fails rendering. Pay attention to your cluster model.")
190 }
191
Richard Felkl0e80d892018-06-20 13:44:54 +0200192 archiveReclassInventory(inventoryAfterFilename)
193
194 sh "diff -u $inventoryBeforeFilename $inventoryAfterFilename > reclass-inventory-diff.out || true"
195 archiveArtifacts artifacts: "reclass-inventory-diff.out"
196
azvyagintsev6dac3802018-11-09 15:11:30 +0200197 if (UPGRADE_SALTSTACK.toBoolean()) {
Richard Felkl0e80d892018-06-20 13:44:54 +0200198 salt.enforceState(venvPepper, "I@linux:system", 'linux.system.repo', true)
199
200 updateSaltStack("I@salt:master", '["salt-master", "salt-common", "salt-api", "salt-minion"]')
201
202 updateSaltStack("I@salt:minion and not I@salt:master", '["salt-minion"]')
203 }
204
azvyagintsev6dac3802018-11-09 15:11:30 +0200205 if (UPDATE_PIPELINES.toBoolean()) {
Richard Felkl970e0082018-06-12 18:00:51 +0200206 triggerMirrorJob("git-mirror-downstream-mk-pipelines")
207 triggerMirrorJob("git-mirror-downstream-pipeline-library")
208 }
209
210 salt.enforceState(venvPepper, "I@jenkins:client", 'jenkins.client', true)
211
212 salt.cmdRun(venvPepper, "I@salt:master", "salt -C 'I@jenkins:client and I@docker:client' state.sls docker.client --async")
213
214 sleep(180)
215
216 common.infoMsg("Checking if Docker containers are up")
217
azvyagintsev6dac3802018-11-09 15:11:30 +0200218 try {
219 common.retry(10, 30) {
Richard Felkl970e0082018-06-12 18:00:51 +0200220 salt.cmdRun(venvPepper, 'I@jenkins:client and I@docker:client', "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
221 }
222 }
azvyagintsev6dac3802018-11-09 15:11:30 +0200223 catch (Exception ex) {
Richard Felkl970e0082018-06-12 18:00:51 +0200224 error("Docker containers for CI/CD services are having troubles with starting.")
225 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100226 }
227 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100228 catch (Throwable e) {
229 // If there was an error or exception thrown, the build failed
230 currentBuild.result = "FAILURE"
231 throw e
Richard Felkl26cae4d2017-12-19 00:19:16 +0100232 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100233 }
Jakub Josef2c21c6c2018-02-08 18:51:42 +0100234}