blob: 5178ca5c254359027e290aad85d0bc413228b93e [file] [log] [blame]
Sergey Kolekonovba203982016-12-21 18:32:17 +04001package com.mirantis.mk
2
3/**
4 *
5 * Python functions
6 *
7 */
8
9/**
10 * Install python virtualenv
11 *
Vladislav Naumov11103862017-07-19 17:02:39 +030012 * @param path Path to virtualenv
13 * @param python Version of Python (python/python3)
14 * @param reqs Environment requirements in list format
15 * @param reqs_path Environment requirements path in str format
Sergey Kolekonovba203982016-12-21 18:32:17 +040016 */
Tomáš Kukrál69c25452017-07-27 14:59:40 +020017def setupVirtualenv(path, python = 'python2', reqs=[], reqs_path=null, clean=false) {
18 def common = new com.mirantis.mk.Common()
19
Yuriy Taraday67352e92017-10-12 10:54:23 +000020 def virtualenv_cmd = "[ -d ${path} ] || virtualenv ${path} --python ${python}"
Tomáš Kukrál69c25452017-07-27 14:59:40 +020021
22 if (clean) {
23 common.infoMsg("Cleaning venv directory " + path)
24 sh("rm -rf \"${path}\"")
25 }
26
27 common.infoMsg("[Python ${path}] Setup ${python} environment")
Sergey Kolekonovba203982016-12-21 18:32:17 +040028 sh(returnStdout: true, script: virtualenv_cmd)
Yuriy Taraday67352e92017-10-12 10:54:23 +000029 try {
30 runVirtualenvCommand(path, "pip install -U setuptools pip")
31 } catch(Exception e) {
Jakub Josef781e6ec2017-10-18 14:13:13 +020032 common.warningMsg("Setuptools and pip cannot be updated, you might be offline")
Yuriy Taraday67352e92017-10-12 10:54:23 +000033 }
Vladislav Naumov11103862017-07-19 17:02:39 +030034 if (reqs_path==null) {
35 def args = ""
36 for (req in reqs) {
37 args = args + "${req}\n"
38 }
39 writeFile file: "${path}/requirements.txt", text: args
40 reqs_path = "${path}/requirements.txt"
Sergey Kolekonovba203982016-12-21 18:32:17 +040041 }
Vladislav Naumov11103862017-07-19 17:02:39 +030042 runVirtualenvCommand(path, "pip install -r ${reqs_path}")
Sergey Kolekonovba203982016-12-21 18:32:17 +040043}
44
45/**
46 * Run command in specific python virtualenv
47 *
48 * @param path Path to virtualenv
49 * @param cmd Command to be executed
50 */
51def runVirtualenvCommand(path, cmd) {
Tomáš Kukrál69c25452017-07-27 14:59:40 +020052 def common = new com.mirantis.mk.Common()
53
Jakub Josef0164dc12017-03-28 16:33:46 +020054 virtualenv_cmd = ". ${path}/bin/activate > /dev/null; ${cmd}"
Tomáš Kukrál69c25452017-07-27 14:59:40 +020055 common.infoMsg("[Python ${path}] Run command ${cmd}")
Sergey Kolekonovba203982016-12-21 18:32:17 +040056 output = sh(
57 returnStdout: true,
58 script: virtualenv_cmd
59 ).trim()
60 return output
61}
62
Ales Komarekd874d482016-12-26 10:33:29 +010063
64/**
65 * Install docutils in isolated environment
66 *
67 * @param path Path where virtualenv is created
68 */
69def setupDocutilsVirtualenv(path) {
70 requirements = [
71 'docutils',
72 ]
73 setupVirtualenv(path, 'python2', requirements)
74}
75
76
Sergey Kolekonovba203982016-12-21 18:32:17 +040077@NonCPS
78def loadJson(rawData) {
79 return new groovy.json.JsonSlurperClassic().parseText(rawData)
80}
81
82/**
83 * Parse content from markup-text tables to variables
84 *
85 * @param tableStr String representing the table
86 * @param mode Either list (1st row are keys) or item (key, value rows)
87 * @param format Format of the table
88 */
Ales Komarekd874d482016-12-26 10:33:29 +010089def parseTextTable(tableStr, type = 'item', format = 'rest', path = none) {
Ales Komarek0e558ee2016-12-23 13:02:55 +010090 parserFile = "${env.WORKSPACE}/textTableParser.py"
91 parserScript = """import json
92import argparse
93from docutils.parsers.rst import tableparser
94from docutils import statemachine
95
96def parse_item_table(raw_data):
97 i = 1
98 pretty_raw_data = []
99 for datum in raw_data:
100 if datum != "":
101 if datum[3] != ' ' and i > 4:
102 pretty_raw_data.append(raw_data[0])
103 if i == 3:
104 pretty_raw_data.append(datum.replace('-', '='))
105 else:
106 pretty_raw_data.append(datum)
107 i += 1
108 parser = tableparser.GridTableParser()
109 block = statemachine.StringList(pretty_raw_data)
110 docutils_data = parser.parse(block)
111 final_data = {}
112 for line in docutils_data[2]:
113 key = ' '.join(line[0][3]).strip()
114 value = ' '.join(line[1][3]).strip()
115 if key != "":
116 try:
117 value = json.loads(value)
118 except:
119 pass
120 final_data[key] = value
121 i+=1
122 return final_data
123
124def parse_list_table(raw_data):
125 i = 1
126 pretty_raw_data = []
127 for datum in raw_data:
128 if datum != "":
129 if datum[3] != ' ' and i > 4:
130 pretty_raw_data.append(raw_data[0])
131 if i == 3:
132 pretty_raw_data.append(datum.replace('-', '='))
133 else:
134 pretty_raw_data.append(datum)
135 i += 1
136 parser = tableparser.GridTableParser()
137 block = statemachine.StringList(pretty_raw_data)
138 docutils_data = parser.parse(block)
139 final_data = []
140 keys = []
141 for line in docutils_data[1]:
142 for item in line:
143 keys.append(' '.join(item[3]).strip())
144 for line in docutils_data[2]:
145 final_line = {}
146 key = ' '.join(line[0][3]).strip()
147 value = ' '.join(line[1][3]).strip()
148 if key != "":
149 try:
150 value = json.loads(value)
151 except:
152 pass
153 final_data[key] = value
154 i+=1
155 return final_data
156
157def parse_list_table(raw_data):
158 i = 1
159 pretty_raw_data = []
160 for datum in raw_data:
161 if datum != "":
162 if datum[3] != ' ' and i > 4:
163 pretty_raw_data.append(raw_data[0])
164 if i == 3:
165 pretty_raw_data.append(datum.replace('-', '='))
166 else:
167 pretty_raw_data.append(datum)
168 i += 1
169 parser = tableparser.GridTableParser()
170 block = statemachine.StringList(pretty_raw_data)
171 docutils_data = parser.parse(block)
172 final_data = []
173 keys = []
174 for line in docutils_data[1]:
175 for item in line:
176 keys.append(' '.join(item[3]).strip())
177 for line in docutils_data[2]:
178 final_line = {}
179 i = 0
180 for item in line:
181 value = ' '.join(item[3]).strip()
182 try:
183 value = json.loads(value)
184 except:
185 pass
186 final_line[keys[i]] = value
187 i += 1
188 final_data.append(final_line)
189 return final_data
190
191def read_table_file(file):
192 table_file = open(file, 'r')
Ales Komarekc000c152016-12-23 15:32:54 +0100193 raw_data = table_file.read().split('\\n')
Ales Komarek0e558ee2016-12-23 13:02:55 +0100194 table_file.close()
195 return raw_data
196
197parser = argparse.ArgumentParser()
198parser.add_argument('-f','--file', help='File with table data', required=True)
199parser.add_argument('-t','--type', help='Type of table (list/item)', required=True)
200args = vars(parser.parse_args())
201
202raw_data = read_table_file(args['file'])
203
204if args['type'] == 'list':
205 final_data = parse_list_table(raw_data)
206else:
207 final_data = parse_item_table(raw_data)
208
209print json.dumps(final_data)
210"""
211 writeFile file: parserFile, text: parserScript
Sergey Kolekonovba203982016-12-21 18:32:17 +0400212 tableFile = "${env.WORKSPACE}/prettytable.txt"
213 writeFile file: tableFile, text: tableStr
Ales Komarekd874d482016-12-26 10:33:29 +0100214
215 cmd = "python ${parserFile} --file '${tableFile}' --type ${type}"
216 if (path) {
Ales Komarekc6d28dd2016-12-28 12:59:38 +0100217 rawData = runVirtualenvCommand(path, cmd)
Ales Komarekd874d482016-12-26 10:33:29 +0100218 }
219 else {
220 rawData = sh (
221 script: cmd,
222 returnStdout: true
223 ).trim()
224 }
Sergey Kolekonovba203982016-12-21 18:32:17 +0400225 data = loadJson(rawData)
226 echo("[Parsed table] ${data}")
227 return data
228}
229
230/**
231 * Install cookiecutter in isolated environment
232 *
233 * @param path Path where virtualenv is created
234 */
235def setupCookiecutterVirtualenv(path) {
236 requirements = [
237 'cookiecutter',
Jakub Josef4df78272017-04-26 14:36:36 +0200238 'jinja2==2.8.1',
239 'PyYAML==3.12'
Sergey Kolekonovba203982016-12-21 18:32:17 +0400240 ]
241 setupVirtualenv(path, 'python2', requirements)
242}
243
244/**
245 * Generate the cookiecutter templates with given context
246 *
Jakub Josef4e10c372017-04-26 14:13:50 +0200247 * @param template template
248 * @param context template context
249 * @param path Path where virtualenv is created (optional)
250 * @param templatePath path to cookiecutter template repo (optional)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400251 */
Jakub Josef4e10c372017-04-26 14:13:50 +0200252def buildCookiecutterTemplate(template, context, outputDir = '.', path = null, templatePath = ".") {
Tomáš Kukráldad7b462017-03-27 13:53:05 +0200253 configFile = "default_config.yaml"
254 configString = "default_context:\n"
Tomáš Kukrál6de85042017-04-12 17:49:05 +0200255 writeFile file: configFile, text: context
Jakub Josef4e61cc02017-04-26 14:29:09 +0200256 command = ". ${path}/bin/activate; if [ -f ${templatePath}/generate.py ]; then python ${templatePath}/generate.py --config-file ${configFile} --template ${template} --output-dir ${outputDir}; else cookiecutter --config-file ${configFile} --output-dir ${outputDir} --overwrite-if-exists --verbose --no-input ${template}; fi"
Sergey Kolekonovba203982016-12-21 18:32:17 +0400257 output = sh (returnStdout: true, script: command)
258 echo("[Cookiecutter build] Output: ${output}")
259}
260
261/**
262 * Install jinja rendering in isolated environment
263 *
264 * @param path Path where virtualenv is created
265 */
266def setupJinjaVirtualenv(path) {
267 requirements = [
268 'jinja2-cli',
269 'pyyaml',
270 ]
271 setupVirtualenv(path, 'python2', requirements)
272}
273
274/**
275 * Generate the Jinja templates with given context
276 *
277 * @param path Path where virtualenv is created
278 */
279def jinjaBuildTemplate (template, context, path = none) {
280 contextFile = "jinja_context.yml"
281 contextString = ""
282 for (parameter in context) {
283 contextString = "${contextString}${parameter.key}: ${parameter.value}\n"
284 }
285 writeFile file: contextFile, text: contextString
286 cmd = "jinja2 ${template} ${contextFile} --format=yaml"
287 data = sh (returnStdout: true, script: cmd)
288 echo(data)
289 return data
290}
Oleg Grigorovbec45582017-09-12 20:29:24 +0300291
292/**
293 * Install salt-pepper in isolated environment
294 *
295 * @param path Path where virtualenv is created
chnydaa0dbb252017-10-05 10:46:09 +0200296 * @param url SALT_MASTER_URL
297 * @param credentialsId Credentials to salt api
Oleg Grigorovbec45582017-09-12 20:29:24 +0300298 */
chnydaa0dbb252017-10-05 10:46:09 +0200299def setupPepperVirtualenv(path, url, credentialsId) {
300 def common = new com.mirantis.mk.Common()
301
302 // virtualenv setup
chnydab38216a2017-10-12 09:46:32 +0200303 requirements = ['salt-pepper']
304 setupVirtualenv(path, 'python2', requirements)
chnydaa0dbb252017-10-05 10:46:09 +0200305
306 // pepperrc creation
307 rcFile = "${path}/pepperrc"
308 creds = common.getPasswordCredentials(credentialsId)
309 rc = """\
310[main]
311SALTAPI_EAUTH=pam
312SALTAPI_URL=${url}
313SALTAPI_USER=${creds.username}
314SALTAPI_PASS=${creds.password.toString()}
315"""
316 writeFile file: rcFile, text: rc
317 return rcFile
Jakub Josefd067f612017-09-26 13:42:56 +0200318}