blob: d5c0e77f5a9287a8cce80cf170fefa0ddfd554c2 [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
38 common.retry(10, 30){
39 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.")
98 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 -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")
Jakub Josefa63f9862018-01-11 17:58:38 +0100109 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100110
Jakub Josefa63f9862018-01-11 17:58:38 +0100111 if(UPDATE_LOCAL_REPOS.toBoolean()){
112 stage("Update local repos"){
113 common.infoMsg("Updating local repositories")
Sam Stoelingaaab79702018-04-09 18:49:39 -0700114
115 def engine = salt.getPillar(venvPepper, 'I@aptly:server', "aptly:server:source:engine")
116 runningOnDocker = engine.get("return")[0].containsValue("docker")
117
118 if (runningOnDocker) {
119 common.infoMsg("Aptly is running as Docker container")
120 }
121 else {
122 common.infoMsg("Aptly isn't running as Docker container. Going to use aptly user for executing aptly commands")
123 }
124
Richard Felkl970e0082018-06-12 18:00:51 +0200125 salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name/cicd/aptly && git checkout $MCP_VERSION")
126
Sam Stoelingaaab79702018-04-09 18:49:39 -0700127 if(runningOnDocker){
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100128 salt.cmdRun(venvPepper, 'I@aptly:server', "aptly mirror list --raw | grep -E '*' | xargs -n 1 aptly mirror drop -force", true, null, true)
129 }
130 else{
131 salt.cmdRun(venvPepper, 'I@aptly:server', "aptly mirror list --raw | grep -E '*' | xargs -n 1 aptly mirror drop -force", true, null, true, ['runas=aptly'])
132 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100133
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100134 salt.enforceState(venvPepper, 'I@aptly:server', 'aptly', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100135
Sam Stoelingaaab79702018-04-09 18:49:39 -0700136 if(runningOnDocker){
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100137 salt.runSaltProcessStep(venvPepper, 'I@aptly:server', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv"], null, true)
138 salt.runSaltProcessStep(venvPepper, 'I@aptly:server', 'cmd.script', ['salt://aptly/files/aptly_publish_update.sh', "args=-frv -u http://10.99.0.1:8080"], null, true)
139 }
140 else{
141 salt.runSaltProcessStep(venvPepper, 'I@aptly:server', 'cmd.script', ['salt://aptly/files/aptly_mirror_update.sh', "args=-sv", 'runas=aptly'], null, true)
142 salt.runSaltProcessStep(venvPepper, 'I@aptly:server', 'cmd.script', ['salt://aptly/files/aptly_publish_update.sh', "args=-afrv", 'runas=aptly'], null, true)
143 }
Richard Felkl79d7df12018-01-05 16:40:11 +0100144
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100145 salt.enforceState(venvPepper, 'I@aptly:server', 'docker.client.registry', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100146
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100147 salt.enforceState(venvPepper, 'I@aptly:server', 'debmirror', true)
Richard Felkl26cae4d2017-12-19 00:19:16 +0100148
Richard Felkl5f7fdaf2018-02-15 15:38:31 +0100149 salt.enforceState(venvPepper, 'I@aptly:server', 'git.server', true)
150
151 salt.enforceState(venvPepper, 'I@aptly:server', '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")
158 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades salt-formula-*")
Richard Felkl0e80d892018-06-20 13:44:54 +0200159
160 def inventoryBeforeFilename = "reclass-inventory-before.out"
161 def inventoryAfterFilename = "reclass-inventory-after.out"
162
163 archiveReclassInventory(inventoryBeforeFilename)
164
165 salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$MCP_VERSION/4' /etc/apt/sources.list.d/mcp_extra.list")
166 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")
167 salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades reclass")
168
Richard Felkl970e0082018-06-12 18:00:51 +0200169 salt.fullRefresh(venvPepper, 'I@salt:master')
Jakub Josefa63f9862018-01-11 17:58:38 +0100170
Richard Felkl970e0082018-06-12 18:00:51 +0200171 try{
172 salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
173 }
174 catch(Exception ex){
175 error("Reclass fails rendering. Pay attention to your cluster model.")
176 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100177
Richard Felkl970e0082018-06-12 18:00:51 +0200178 salt.fullRefresh(venvPepper, '*')
179
180 try{
181 salt.cmdRun(venvPepper, 'I@salt:master', "reclass-salt --top")
182 }
183 catch(Exception ex){
184 error("Reclass fails rendering. Pay attention to your cluster model.")
185 }
186
Richard Felkl0e80d892018-06-20 13:44:54 +0200187 archiveReclassInventory(inventoryAfterFilename)
188
189 sh "diff -u $inventoryBeforeFilename $inventoryAfterFilename > reclass-inventory-diff.out || true"
190 archiveArtifacts artifacts: "reclass-inventory-diff.out"
191
192 if(UPGRADE_SALTSTACK.toBoolean()){
193 salt.enforceState(venvPepper, "I@linux:system", 'linux.system.repo', true)
194
195 updateSaltStack("I@salt:master", '["salt-master", "salt-common", "salt-api", "salt-minion"]')
196
197 updateSaltStack("I@salt:minion and not I@salt:master", '["salt-minion"]')
198 }
199
Richard Felkl970e0082018-06-12 18:00:51 +0200200 if(UPDATE_PIPELINES.toBoolean()){
201 triggerMirrorJob("git-mirror-downstream-mk-pipelines")
202 triggerMirrorJob("git-mirror-downstream-pipeline-library")
203 }
204
205 salt.enforceState(venvPepper, "I@jenkins:client", 'jenkins.client', true)
206
207 salt.cmdRun(venvPepper, "I@salt:master", "salt -C 'I@jenkins:client and I@docker:client' state.sls docker.client --async")
208
209 sleep(180)
210
211 common.infoMsg("Checking if Docker containers are up")
212
213 try{
214 common.retry(10, 30){
215 salt.cmdRun(venvPepper, 'I@jenkins:client and I@docker:client', "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
216 }
217 }
218 catch(Exception ex){
219 error("Docker containers for CI/CD services are having troubles with starting.")
220 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100221 }
222 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100223 catch (Throwable e) {
224 // If there was an error or exception thrown, the build failed
225 currentBuild.result = "FAILURE"
226 throw e
Richard Felkl26cae4d2017-12-19 00:19:16 +0100227 }
Richard Felkl26cae4d2017-12-19 00:19:16 +0100228 }
Jakub Josef2c21c6c2018-02-08 18:51:42 +0100229}