blob: 8c4d907b4f7b8f51517eec81fbca61824645683c [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]
88 if(UPDATE_CLUSTER_MODEL.toBoolean()){
89 try{
90 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/ && git diff-index --quiet HEAD --")
91 }
92 catch(Exception ex){
93 error("You have uncommited changes in your Reclass cluster model repository. Please commit or reset them and rerun the pipeline.")
94 }
Martin Polreich4d606f52018-08-06 10:40:11 +020095 def dateTime = common.getDatetime()
Richard Felkl970e0082018-06-12 18:00:51 +020096 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && grep -r --exclude-dir=aptly -l 'apt_mk_version: .*' * | xargs sed -i 's/apt_mk_version: .*/apt_mk_version: \"$MCP_VERSION\"/g'")
Martin Polreich4d606f52018-08-06 10:40:11 +020097 common.infoMsg("The following changes were made to the cluster model and will be commited. 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.")
Sergey1b81c062018-10-16 17:10:21 +040098 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git diff")
99 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && git status && git add -u && git commit --allow-empty -m 'Cluster model update to the release $MCP_VERSION on $dateTime'")
Richard Felkl970e0082018-06-12 18:00:51 +0200100 }
101
102 try{
103 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git diff-index --quiet HEAD --")
104 }
105 catch(Exception ex){
106 error("You have unstaged changes in your Reclass system model repository. Please reset them and rerun the pipeline.")
107 }
Richard Felkl65e38372018-07-30 11:46:43 +0200108 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git checkout $gitMcpVersion")
Sergey1b81c062018-10-16 17:10:21 +0400109 // Add new defaults
110 common.infoMsg("Add new defaults")
111 salt.cmdRun(venvPepper, 'I@salt:master', "grep '^- system.defaults\$' /srv/salt/reclass/classes/cluster/*/infra/init.yml || " +
112 "sed -i 's/^classes:/classes:\\n- system.defaults/' /srv/salt/reclass/classes/cluster/*/infra/init.yml")
113 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
Jakub Josefa63f9862018-01-11 17:58:38 +0100116 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]
Jakub Josefa63f9862018-01-11 17:58:38 +0100118 stage("Update local repos"){
119 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")
126 }
127 else {
128 common.infoMsg("Aptly isn't running as Docker container. Going to use aptly user for executing aptly commands")
129 }
130
131 if(runningOnDocker){
Sergey1b81c062018-10-16 17:10:21 +0400132 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 +0100133 }
134 else{
Sergey1b81c062018-10-16 17:10:21 +0400135 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 +0100136 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100137
Sergey1b81c062018-10-16 17:10:21 +0400138 salt.enforceState(venvPepper, 'I@aptly:publisher', 'aptly', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100139
Sam Stoelingaaab79702018-04-09 18:49:39 -0700140 if(runningOnDocker){
Sergey1b81c062018-10-16 17:10:21 +0400141 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv"], null, true)
142 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 +0100143 }
144 else{
Sergey1b81c062018-10-16 17:10:21 +0400145 salt.runSaltProcessStep(venvPepper, 'I@aptly:publisher', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv", 'runas=aptly'], null, true)
146 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 +0100147 }
Richard Felkl79d7df12018-01-05 16:40:11 +0100148
Sergey1b81c062018-10-16 17:10:21 +0400149 salt.enforceState(venvPepper, 'I@aptly:publisher', 'docker.client.registry', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100150
Sergey1b81c062018-10-16 17:10:21 +0400151 salt.enforceState(venvPepper, 'I@aptly:publisher', 'debmirror', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100152
Sergey1b81c062018-10-16 17:10:21 +0400153 salt.enforceState(venvPepper, 'I@aptly:publisher', 'git.server', true)
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100154
Sergey1b81c062018-10-16 17:10:21 +0400155 salt.enforceState(venvPepper, 'I@aptly:publisher', 'linux.system.file', true)
Jakub Josefa63f9862018-01-11 17:58:38 +0100156 }
157 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100158
Richard Felkl970e0082018-06-12 18:00:51 +0200159 stage("Update Drivetrain"){
160 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$MCP_VERSION/4' /etc/apt/sources.list.d/mcp_salt.list")
161 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 +0400162 // Workaround for PROD-22108
163 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get purge -y salt-formula-octavia && " +
164 "apt-get install -y salt-formula-octavia")
165 // End workaround for PROD-22108
Richard Felkl970e0082018-06-12 18:00:51 +0200166 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades salt-formula-*")
Richard Felkl0e80d892018-06-20 13:44:54 +0200167
168 def inventoryBeforeFilename = "reclass-inventory-before.out"
169 def inventoryAfterFilename = "reclass-inventory-after.out"
170
171 archiveReclassInventory(inventoryBeforeFilename)
172
173 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$MCP_VERSION/4' /etc/apt/sources.list.d/mcp_extra.list")
174 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")
175 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades reclass")
176
Richard Felkl970e0082018-06-12 18:00:51 +0200177 salt.fullRefresh(venvPepper, 'I@salt:master')
Jakub Josefa63f9862018-01-11 17:58:38 +0100178
Richard Felkl970e0082018-06-12 18:00:51 +0200179 try{
180 salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
181 }
182 catch(Exception ex){
183 error("Reclass fails rendering. Pay attention to your cluster model.")
184 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100185
Richard Felkl970e0082018-06-12 18:00:51 +0200186 salt.fullRefresh(venvPepper, '*')
187
188 try{
189 salt.cmdRun(venvPepper, 'I@salt:master', "reclass-salt --top")
190 }
191 catch(Exception ex){
192 error("Reclass fails rendering. Pay attention to your cluster model.")
193 }
194
Richard Felkl0e80d892018-06-20 13:44:54 +0200195 archiveReclassInventory(inventoryAfterFilename)
196
197 sh "diff -u $inventoryBeforeFilename $inventoryAfterFilename > reclass-inventory-diff.out || true"
198 archiveArtifacts artifacts: "reclass-inventory-diff.out"
199
200 if(UPGRADE_SALTSTACK.toBoolean()){
201 salt.enforceState(venvPepper, "I@linux:system", 'linux.system.repo', true)
202
203 updateSaltStack("I@salt:master", '["salt-master", "salt-common", "salt-api", "salt-minion"]')
204
205 updateSaltStack("I@salt:minion and not I@salt:master", '["salt-minion"]')
206 }
207
Richard Felkl970e0082018-06-12 18:00:51 +0200208 if(UPDATE_PIPELINES.toBoolean()){
209 triggerMirrorJob("git-mirror-downstream-mk-pipelines")
210 triggerMirrorJob("git-mirror-downstream-pipeline-library")
211 }
212
213 salt.enforceState(venvPepper, "I@jenkins:client", 'jenkins.client', true)
214
215 salt.cmdRun(venvPepper, "I@salt:master", "salt -C 'I@jenkins:client and I@docker:client' state.sls docker.client --async")
216
217 sleep(180)
218
219 common.infoMsg("Checking if Docker containers are up")
220
221 try{
222 common.retry(10, 30){
223 salt.cmdRun(venvPepper, 'I@jenkins:client and I@docker:client', "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
224 }
225 }
226 catch(Exception ex){
227 error("Docker containers for CI/CD services are having troubles with starting.")
228 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100229 }
230 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100231 catch (Throwable e) {
232 // If there was an error or exception thrown, the build failed
233 currentBuild.result = "FAILURE"
234 throw e
Richard Felkl26cae4d2017-12-19 00:19:16 +0100235 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100236 }
Jakub Josef2c21c6c2018-02-08 18:51:42 +0100237}