blob: 566caa99a2960126d31c90b96eef63522e7afb1c [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
8 * 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
Richard Felkl970e0082018-06-12 18:00:51 +020023def triggerMirrorJob(jobName){
24 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
Richard Felkl0e80d892018-06-20 13:44:54 +020033def updateSaltStack(target, pkgs){
34 try{
35 salt.runSaltProcessStep(venvPepper, target, 'pkg.install', ["force_yes=True", "pkgs='$pkgs'"], null, true, 5)
36 }catch(Exception ex){}
37
Sergey1b81c062018-10-16 17:10:21 +040038 common.retry(20, 60){
Richard Felkl0e80d892018-06-20 13:44:54 +020039 salt.minionsReachable(venvPepper, 'I@salt:master', '*')
40 def running = salt.runSaltProcessStep(venvPepper, target, 'saltutil.running', [], null, true, 5)
41 for(value in running.get("return")[0].values()){
42 if(value != []){
43 throw new Exception("Not all salt-minions are ready for execution")
44 }
45 }
46 }
47
48 def saltVersion = salt.getPillar(venvPepper, 'I@salt:master', "_param:salt_version").get("return")[0].values()[0]
Richard Felklf23257e2018-08-06 09:24:23 +020049 def saltMinionVersions = salt.cmdRun(venvPepper, target, "apt-cache policy salt-common | awk '/Installed/ && /$saltVersion/'").get("return")
Richard Felkl0e80d892018-06-20 13:44:54 +020050 def saltMinionVersion = ""
51
52 for(minion in saltMinionVersions[0].keySet()){
53 saltMinionVersion = saltMinionVersions[0].get(minion).replace("Salt command execution success","").trim()
54 if(saltMinionVersion == ""){
55 error("Installed version of Salt on $minion doesn't match specified version in the model.")
56 }
57 }
58}
59
60def archiveReclassInventory(filename){
61 def ret = salt.cmdRun(venvPepper, 'I@salt:master', "reclass -i", true, null, false)
62 def reclassInv = ret.values()[0]
63 writeFile file: filename, text: reclassInv.toString()
64 archiveArtifacts artifacts: "$filename"
65}
66
Martin Polreich965c9032018-08-09 16:33:57 +020067def pipelineTimeout = 12
68if (common.validInputParam('PIPELINE_TIMEOUT') && PIPELINE_TIMEOUT.isInteger()) {
69 pipelineTimeout = "${PIPELINE_TIMEOUT}".toInteger()
70}
71
72timeout(time: pipelineTimeout, unit: 'HOURS') {
Jakub Josefa63f9862018-01-11 17:58:38 +010073 node("python") {
74 try {
Richard Felkl65e38372018-07-30 11:46:43 +020075 def gitMcpVersion = MCP_VERSION
Richard Felkl0e80d892018-06-20 13:44:54 +020076 workspace = common.getWorkspace()
Jakub Josefa63f9862018-01-11 17:58:38 +010077 python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Richard Felkl26cae4d2017-12-19 00:19:16 +010078
Richard Felkl970e0082018-06-12 18:00:51 +020079 if(MCP_VERSION == ""){
80 error("You must specify MCP version")
81 }
Richard Felkl65e38372018-07-30 11:46:43 +020082 if(MCP_VERSION == "testing"){
83 gitMcpVersion = "master"
84 }
Richard Felkl970e0082018-06-12 18:00:51 +020085
Jakub Josefa63f9862018-01-11 17:58:38 +010086 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]
Richard Felkl970e0082018-06-12 18:00:51 +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 }
91 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 }
Sergey382581a2018-10-25 12:22:26 +040094 if(UPDATE_CLUSTER_MODEL.toBoolean()){
95 def dateTime = common.getDatetime()
96 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && " +
97 "grep -r --exclude-dir=apty -l 'apt_mk_version: .*' * | xargs sed -i 's/apt_mk_version: .*/apt_mk_version: \"$MCP_VERSION\"/g'")
98 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git checkout $gitMcpVersion")
99 // Add new defaults
100 common.infoMsg("Add new defaults")
101 salt.cmdRun(venvPepper, 'I@salt:master', "grep '^- system.defaults\$' /srv/salt/reclass/classes/cluster/$cluster_name/infra/init.yml || " +
102 "sed -i 's/^classes:/classes:\\n- system.defaults/' /srv/salt/reclass/classes/cluster/$cluster_name/infra/init.yml")
103 common.infoMsg("The following changes were made to the cluster model and will be commited. " +
104 "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.")
105 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git diff")
106 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git status && " +
107 "git add -u && git commit --allow-empty -m 'Cluster model update to the release $MCP_VERSION on $dateTime'")
108 }
Sergey1b81c062018-10-16 17:10:21 +0400109 salt.enforceState(venvPepper, 'I@salt:master', 'reclass.storage', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100110 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100111
Jakub Josefa63f9862018-01-11 17:58:38 +0100112 if(UPDATE_LOCAL_REPOS.toBoolean()){
Sergey1b81c062018-10-16 17:10:21 +0400113 def cluster_name = salt.getPillar(venvPepper, 'I@salt:master', "_param:cluster_name").get("return")[0].values()[0]
Jakub Josefa63f9862018-01-11 17:58:38 +0100114 stage("Update local repos"){
115 common.infoMsg("Updating local repositories")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700116
Sergey1b81c062018-10-16 17:10:21 +0400117 def engine = salt.getPillar(venvPepper, 'I@aptly:publisher', "aptly:publisher:source:engine")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700118 runningOnDocker = engine.get("return")[0].containsValue("docker")
119
120 if (runningOnDocker) {
121 common.infoMsg("Aptly is running as Docker container")
122 }
123 else {
124 common.infoMsg("Aptly isn't running as Docker container. Going to use aptly user for executing aptly commands")
125 }
126
127 if(runningOnDocker){
Sergey1b81c062018-10-16 17:10:21 +0400128 salt.cmdRun(venvPepper, 'I@aptly:publisher', "aptly mirror list --raw | grep -E '*' | xargs -n 1 aptly mirror drop -force", true, null, true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100129 }
130 else{
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, ['runas=aptly'])
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100132 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100133
Sergey1b81c062018-10-16 17:10:21 +0400134 salt.enforceState(venvPepper, 'I@aptly:publisher', 'aptly', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100135
Sam Stoelingaaab79702018-04-09 18:49:39 -0700136 if(runningOnDocker){
Sergey1b81c062018-10-16 17:10:21 +0400137 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv"], null, true)
138 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)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100139 }
140 else{
Sergey1b81c062018-10-16 17:10:21 +0400141 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv", 'runas=aptly'], null, true)
142 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 +0100143 }
Richard Felkl79d7df12018-01-05 16:40:11 +0100144
Sergey1b81c062018-10-16 17:10:21 +0400145 salt.enforceState(venvPepper, 'I@aptly:publisher', 'docker.client.registry', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100146
Sergey1b81c062018-10-16 17:10:21 +0400147 salt.enforceState(venvPepper, 'I@aptly:publisher', 'debmirror', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100148
Sergey1b81c062018-10-16 17:10:21 +0400149 salt.enforceState(venvPepper, 'I@aptly:publisher', 'git.server', true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100150
Sergey1b81c062018-10-16 17:10:21 +0400151 salt.enforceState(venvPepper, 'I@aptly:publisher', 'linux.system.file', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100152 }
153 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100154
Richard Felkl970e0082018-06-12 18:00:51 +0200155 stage("Update Drivetrain"){
156 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$MCP_VERSION/4' /etc/apt/sources.list.d/mcp_salt.list")
157 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 +0400158 // Workaround for PROD-22108
159 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get purge -y salt-formula-octavia && " +
160 "apt-get install -y salt-formula-octavia")
161 // End workaround for PROD-22108
Richard Felkl970e0082018-06-12 18:00:51 +0200162 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades salt-formula-*")
Richard Felkl0e80d892018-06-20 13:44:54 +0200163
164 def inventoryBeforeFilename = "reclass-inventory-before.out"
165 def inventoryAfterFilename = "reclass-inventory-after.out"
166
167 archiveReclassInventory(inventoryBeforeFilename)
168
169 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$MCP_VERSION/4' /etc/apt/sources.list.d/mcp_extra.list")
170 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")
171 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades reclass")
172
Richard Felkl970e0082018-06-12 18:00:51 +0200173 salt.fullRefresh(venvPepper, 'I@salt:master')
Jakub Josefa63f9862018-01-11 17:58:38 +0100174
Richard Felkl970e0082018-06-12 18:00:51 +0200175 try{
176 salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
177 }
178 catch(Exception ex){
179 error("Reclass fails rendering. Pay attention to your cluster model.")
180 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100181
Richard Felkl970e0082018-06-12 18:00:51 +0200182 salt.fullRefresh(venvPepper, '*')
183
184 try{
185 salt.cmdRun(venvPepper, 'I@salt:master', "reclass-salt --top")
186 }
187 catch(Exception ex){
188 error("Reclass fails rendering. Pay attention to your cluster model.")
189 }
190
Richard Felkl0e80d892018-06-20 13:44:54 +0200191 archiveReclassInventory(inventoryAfterFilename)
192
193 sh "diff -u $inventoryBeforeFilename $inventoryAfterFilename > reclass-inventory-diff.out || true"
194 archiveArtifacts artifacts: "reclass-inventory-diff.out"
195
196 if(UPGRADE_SALTSTACK.toBoolean()){
197 salt.enforceState(venvPepper, "I@linux:system", 'linux.system.repo', true)
198
199 updateSaltStack("I@salt:master", '["salt-master", "salt-common", "salt-api", "salt-minion"]')
200
201 updateSaltStack("I@salt:minion and not I@salt:master", '["salt-minion"]')
202 }
203
Richard Felkl970e0082018-06-12 18:00:51 +0200204 if(UPDATE_PIPELINES.toBoolean()){
205 triggerMirrorJob("git-mirror-downstream-mk-pipelines")
206 triggerMirrorJob("git-mirror-downstream-pipeline-library")
207 }
208
209 salt.enforceState(venvPepper, "I@jenkins:client", 'jenkins.client', true)
210
211 salt.cmdRun(venvPepper, "I@salt:master", "salt -C 'I@jenkins:client and I@docker:client' state.sls docker.client --async")
212
213 sleep(180)
214
215 common.infoMsg("Checking if Docker containers are up")
216
217 try{
218 common.retry(10, 30){
219 salt.cmdRun(venvPepper, 'I@jenkins:client and I@docker:client', "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
220 }
221 }
222 catch(Exception ex){
223 error("Docker containers for CI/CD services are having troubles with starting.")
224 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100225 }
226 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100227 catch (Throwable e) {
228 // If there was an error or exception thrown, the build failed
229 currentBuild.result = "FAILURE"
230 throw e
Richard Felkl26cae4d2017-12-19 00:19:16 +0100231 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100232 }
Jakub Josef2c21c6c2018-02-08 18:51:42 +0100233}