blob: 9d36f38e6a8f5dbb71cf60321f3fa958630c22f7 [file] [log] [blame]
Ales Komarek1fe5b8f2017-03-06 11:07:54 +01001/**
Ales Komarek374cc382017-03-16 08:49:01 +01002 * Update packages on given nodes
Ales Komarek1fe5b8f2017-03-06 11:07:54 +01003 *
4 * Expected parameters:
Ales Komarek374cc382017-03-16 08:49:01 +01005 * SALT_MASTER_CREDENTIALS Credentials to the Salt API.
6 * SALT_MASTER_URL Full Salt API address [https://10.10.10.1:8000].
7 * TARGET_SERVERS Salt compound target to match nodes to be updated [*, G@osfamily:debian].
8 * TARGET_PACKAGES Space delimited list of packages to be updates [package1=version package2=version], empty string means all updating all packages to the latest version.
Jiri Broulik9b73d6c2017-06-02 12:27:05 +02009 * TARGET_SUBSET_TEST Number of nodes to list package updates, empty string means all targetted nodes.
10 * TARGET_SUBSET_LIVE Number of selected nodes to live apply selected package update.
11 * TARGET_BATCH_LIVE Batch size for the complete live package update on all nodes, empty string means apply to all targetted nodes.
Ales Komarek1fe5b8f2017-03-06 11:07:54 +010012 *
13**/
Pavel Cizinskyaf889c32018-08-15 15:20:42 +020014pepperEnv = "pepperEnv"
15salt = new com.mirantis.mk.Salt()
Ales Komarek1fe5b8f2017-03-06 11:07:54 +010016def common = new com.mirantis.mk.Common()
chnyda625f4b42017-10-11 14:10:31 +020017def python = new com.mirantis.mk.Python()
Ales Komarek374cc382017-03-16 08:49:01 +010018def targetTestSubset
19def targetLiveSubset
20def targetLiveAll
21def minions
22def result
23def packages
Jakub Joseff080c142017-03-16 18:22:18 +010024def command
Filip Pytloun43896ed2017-03-29 14:23:32 +020025def commandKwargs
Denis Egorenko0d0c65f2019-02-26 16:05:03 +040026
27def installSaltStack(target, pkgs, masterUpdate = false){
28 salt.cmdRun(pepperEnv, "I@salt:master", "salt -C '${target}' --async pkg.install force_yes=True pkgs='$pkgs'")
29 def minions_reachable = target
30 if (masterUpdate) {
31 // in case of update Salt Master packages - check all minions are good
32 minions_reachable = '*'
33 }
34 salt.checkTargetMinionsReady(['saltId': venvPepper, 'target': target, 'target_reachable': minions_reachable])
Pavel Cizinskyaf889c32018-08-15 15:20:42 +020035}
36
Jakub Josefa63f9862018-01-11 17:58:38 +010037timeout(time: 12, unit: 'HOURS') {
38 node() {
39 try {
Ales Komarek374cc382017-03-16 08:49:01 +010040
Jakub Josefa63f9862018-01-11 17:58:38 +010041 stage('Setup virtualenv for Pepper') {
42 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
Tomáš Kukráld73cef02017-04-05 15:24:57 +020043 }
44
Jakub Josefa63f9862018-01-11 17:58:38 +010045 stage('List target servers') {
46 minions = salt.getMinions(pepperEnv, TARGET_SERVERS)
47
48 if (minions.isEmpty()) {
49 throw new Exception("No minion was targeted")
50 }
51
52 if (TARGET_SUBSET_TEST != "") {
53 targetTestSubset = minions.subList(0, Integer.valueOf(TARGET_SUBSET_TEST)).join(' or ')
54 } else {
55 targetTestSubset = minions.join(' or ')
56 }
57 targetLiveSubset = minions.subList(0, Integer.valueOf(TARGET_SUBSET_LIVE)).join(' or ')
58
59 targetLiveAll = minions.join(' or ')
60 common.infoMsg("Found nodes: ${targetLiveAll}")
61 common.infoMsg("Selected test nodes: ${targetTestSubset}")
62 common.infoMsg("Selected sample nodes: ${targetLiveSubset}")
Ales Komarek374cc382017-03-16 08:49:01 +010063 }
Tomáš Kukráld73cef02017-04-05 15:24:57 +020064
Jakub Josefa63f9862018-01-11 17:58:38 +010065 stage("List package upgrades") {
66 common.infoMsg("Listing all the packages that have a new update available on test nodes: ${targetTestSubset}")
67 salt.runSaltProcessStep(pepperEnv, targetTestSubset, 'pkg.list_upgrades', [], null, true)
68 if(TARGET_PACKAGES != "" && TARGET_PACKAGES != "*"){
69 common.infoMsg("Note that only the ${TARGET_PACKAGES} would be installed from the above list of available updates on the ${targetTestSubset}")
70 }
Sam Stoelingaf52a0422017-08-01 12:26:21 -070071 }
Ales Komarek374cc382017-03-16 08:49:01 +010072
Jakub Josefa63f9862018-01-11 17:58:38 +010073 stage('Confirm live package upgrades on sample') {
74 if(TARGET_PACKAGES==""){
75 timeout(time: 2, unit: 'HOURS') {
76 def userInput = input(
77 id: 'userInput', message: 'Insert package names for update', parameters: [
78 [$class: 'TextParameterDefinition', defaultValue: '', description: 'Package names (or *)', name: 'packages']
79 ])
80 if(userInput!= "" && userInput!= "*"){
81 TARGET_PACKAGES = userInput
82 }
83 }
84 }else{
85 timeout(time: 2, unit: 'HOURS') {
86 input message: "Approve live package upgrades on ${targetLiveSubset} nodes?"
Jakub Josef4a013752017-03-16 17:37:51 +010087 }
88 }
Jakub Josefa63f9862018-01-11 17:58:38 +010089 }
90
91 if (TARGET_PACKAGES != "") {
92 command = "pkg.install"
93 packages = TARGET_PACKAGES.tokenize(' ')
94 commandKwargs = ['only_upgrade': 'true']
95 }else {
96 command = "pkg.upgrade"
97 packages = null
98 }
99
100 stage('Apply package upgrades on sample') {
Pavel Cizinskyaf889c32018-08-15 15:20:42 +0200101 if(packages == null || packages.contains("salt-master") || packages.contains("salt-common") || packages.contains("salt-minion") || packages.contains("salt-api")){
102 def saltTargets = (targetLiveSubset.split(' or ').collect{it as String})
103 for(int i = 0; i < saltTargets.size(); i++ ){
104 common.infoMsg("During salt-minion upgrade on cfg node, pipeline lose connectivy to salt-master for 2 min. If pipeline ended with error rerun pipeline again.")
105 common.retry(10, 5) {
106 if(salt.minionsReachable(pepperEnv, 'I@salt:master', "I@salt:master and ${saltTargets[i]}")){
Denis Egorenko0d0c65f2019-02-26 16:05:03 +0400107 installSaltStack("I@salt:master and ${saltTargets[i]}", '["salt-master", "salt-common", "salt-api", "salt-minion"]', true)
Pavel Cizinskyaf889c32018-08-15 15:20:42 +0200108 }
109 if(salt.minionsReachable(pepperEnv, 'I@salt:master', "I@salt:minion and not I@salt:master and ${saltTargets[i]}")){
110 installSaltStack("I@salt:minion and not I@salt:master and ${saltTargets[i]}", '["salt-minion"]')
111 }
112 }
113 }
114 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100115 out = salt.runSaltCommand(pepperEnv, 'local', ['expression': targetLiveSubset, 'type': 'compound'], command, null, packages, commandKwargs)
116 salt.printSaltCommandResult(out)
Martin Polreich6cb53622018-08-15 16:45:29 +0200117 for(value in out.get("return")[0].values()){
118 if (value.containsKey('result') && value.result == false) {
119 throw new Exception("The package upgrade on sample node has failed. Please check the Salt run result above for more information.")
120 }
121 }
Jakub Josefa63f9862018-01-11 17:58:38 +0100122 }
123
124 stage('Confirm package upgrades on all nodes') {
Jakub Josef4a013752017-03-16 17:37:51 +0100125 timeout(time: 2, unit: 'HOURS') {
Jakub Josefa63f9862018-01-11 17:58:38 +0100126 input message: "Approve live package upgrades on ${targetLiveAll} nodes?"
Jakub Josef4a013752017-03-16 17:37:51 +0100127 }
Ales Komarek374cc382017-03-16 08:49:01 +0100128 }
Jakub Josefc5407c42017-03-16 18:31:10 +0100129
Jakub Josefa63f9862018-01-11 17:58:38 +0100130 stage('Apply package upgrades on all nodes') {
Pavel Cizinskyaf889c32018-08-15 15:20:42 +0200131
132 if(packages == null || packages.contains("salt-master") || packages.contains("salt-common") || packages.contains("salt-minion") || packages.contains("salt-api")){
133 def saltTargets = (targetLiveAll.split(' or ').collect{it as String})
134 for(int i = 0; i < saltTargets.size(); i++ ){
135 common.infoMsg("During salt-minion upgrade on cfg node, pipeline lose connectivy to salt-master for 2 min. If pipeline ended with error rerun pipeline again.")
136 common.retry(10, 5) {
137 if(salt.minionsReachable(pepperEnv, 'I@salt:master', "I@salt:master and ${saltTargets[i]}")){
Denis Egorenko0d0c65f2019-02-26 16:05:03 +0400138 installSaltStack("I@salt:master and ${saltTargets[i]}", '["salt-master", "salt-common", "salt-api", "salt-minion"]', true)
Pavel Cizinskyaf889c32018-08-15 15:20:42 +0200139 }
140 if(salt.minionsReachable(pepperEnv, 'I@salt:master', "I@salt:minion and not I@salt:master and ${saltTargets[i]}")){
141 installSaltStack("I@salt:minion and not I@salt:master and ${saltTargets[i]}", '["salt-minion"]')
142 }
143 }
144 }
145 }
146
Jakub Josefa63f9862018-01-11 17:58:38 +0100147 out = salt.runSaltCommand(pepperEnv, 'local', ['expression': targetLiveAll, 'type': 'compound'], command, null, packages, commandKwargs)
148 salt.printSaltCommandResult(out)
Martin Polreich6cb53622018-08-15 16:45:29 +0200149 for(value in out.get("return")[0].values()){
150 if (value.containsKey('result') && value.result == false) {
151 throw new Exception("The package upgrade on sample node has failed. Please check the Salt run result above for more information.")
152 }
153 }
154 common.warningMsg("Pipeline has finished successfully, but please, check if any packages have been kept back.")
Ales Komarek374cc382017-03-16 08:49:01 +0100155 }
Ales Komarek374cc382017-03-16 08:49:01 +0100156
Jakub Josefa63f9862018-01-11 17:58:38 +0100157 } catch (Throwable e) {
158 // If there was an error or exception thrown, the build failed
159 currentBuild.result = "FAILURE"
160 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
161 throw e
Ales Komarek374cc382017-03-16 08:49:01 +0100162 }
Ales Komarek1fe5b8f2017-03-06 11:07:54 +0100163 }
164}