blob: 0b7716d102b512618c304598f5c7ae33302c9e0f [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
Jakub Josefd067f612017-09-26 13:42:56 +020020 //XXX: hack to fix https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1635463
21 def virtualenv_cmd = "virtualenv ${path} --python ${python} --no-setuptools"
Tomáš Kukrál69c25452017-07-27 14:59:40 +020022
23 if (clean) {
24 common.infoMsg("Cleaning venv directory " + path)
25 sh("rm -rf \"${path}\"")
26 }
27
28 common.infoMsg("[Python ${path}] Setup ${python} environment")
Sergey Kolekonovba203982016-12-21 18:32:17 +040029 sh(returnStdout: true, script: virtualenv_cmd)
Vladislav Naumov11103862017-07-19 17:02:39 +030030 if (reqs_path==null) {
31 def args = ""
32 for (req in reqs) {
33 args = args + "${req}\n"
34 }
35 writeFile file: "${path}/requirements.txt", text: args
36 reqs_path = "${path}/requirements.txt"
Sergey Kolekonovba203982016-12-21 18:32:17 +040037 }
Jakub Josefd067f612017-09-26 13:42:56 +020038 //XXX: hack to fix https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1635463
39 runVirtualenvCommand(path, "pip install setuptools")
Vladislav Naumov11103862017-07-19 17:02:39 +030040 runVirtualenvCommand(path, "pip install -r ${reqs_path}")
Sergey Kolekonovba203982016-12-21 18:32:17 +040041}
42
43/**
44 * Run command in specific python virtualenv
45 *
46 * @param path Path to virtualenv
47 * @param cmd Command to be executed
48 */
49def runVirtualenvCommand(path, cmd) {
Tomáš Kukrál69c25452017-07-27 14:59:40 +020050 def common = new com.mirantis.mk.Common()
51
Jakub Josef0164dc12017-03-28 16:33:46 +020052 virtualenv_cmd = ". ${path}/bin/activate > /dev/null; ${cmd}"
Tomáš Kukrál69c25452017-07-27 14:59:40 +020053 common.infoMsg("[Python ${path}] Run command ${cmd}")
Sergey Kolekonovba203982016-12-21 18:32:17 +040054 output = sh(
55 returnStdout: true,
56 script: virtualenv_cmd
57 ).trim()
58 return output
59}
60
Ales Komarekd874d482016-12-26 10:33:29 +010061
62/**
63 * Install docutils in isolated environment
64 *
65 * @param path Path where virtualenv is created
66 */
67def setupDocutilsVirtualenv(path) {
68 requirements = [
69 'docutils',
70 ]
71 setupVirtualenv(path, 'python2', requirements)
72}
73
74
Sergey Kolekonovba203982016-12-21 18:32:17 +040075@NonCPS
76def loadJson(rawData) {
77 return new groovy.json.JsonSlurperClassic().parseText(rawData)
78}
79
80/**
81 * Parse content from markup-text tables to variables
82 *
83 * @param tableStr String representing the table
84 * @param mode Either list (1st row are keys) or item (key, value rows)
85 * @param format Format of the table
86 */
Ales Komarekd874d482016-12-26 10:33:29 +010087def parseTextTable(tableStr, type = 'item', format = 'rest', path = none) {
Ales Komarek0e558ee2016-12-23 13:02:55 +010088 parserFile = "${env.WORKSPACE}/textTableParser.py"
89 parserScript = """import json
90import argparse
91from docutils.parsers.rst import tableparser
92from docutils import statemachine
93
94def parse_item_table(raw_data):
95 i = 1
96 pretty_raw_data = []
97 for datum in raw_data:
98 if datum != "":
99 if datum[3] != ' ' and i > 4:
100 pretty_raw_data.append(raw_data[0])
101 if i == 3:
102 pretty_raw_data.append(datum.replace('-', '='))
103 else:
104 pretty_raw_data.append(datum)
105 i += 1
106 parser = tableparser.GridTableParser()
107 block = statemachine.StringList(pretty_raw_data)
108 docutils_data = parser.parse(block)
109 final_data = {}
110 for line in docutils_data[2]:
111 key = ' '.join(line[0][3]).strip()
112 value = ' '.join(line[1][3]).strip()
113 if key != "":
114 try:
115 value = json.loads(value)
116 except:
117 pass
118 final_data[key] = value
119 i+=1
120 return final_data
121
122def parse_list_table(raw_data):
123 i = 1
124 pretty_raw_data = []
125 for datum in raw_data:
126 if datum != "":
127 if datum[3] != ' ' and i > 4:
128 pretty_raw_data.append(raw_data[0])
129 if i == 3:
130 pretty_raw_data.append(datum.replace('-', '='))
131 else:
132 pretty_raw_data.append(datum)
133 i += 1
134 parser = tableparser.GridTableParser()
135 block = statemachine.StringList(pretty_raw_data)
136 docutils_data = parser.parse(block)
137 final_data = []
138 keys = []
139 for line in docutils_data[1]:
140 for item in line:
141 keys.append(' '.join(item[3]).strip())
142 for line in docutils_data[2]:
143 final_line = {}
144 key = ' '.join(line[0][3]).strip()
145 value = ' '.join(line[1][3]).strip()
146 if key != "":
147 try:
148 value = json.loads(value)
149 except:
150 pass
151 final_data[key] = value
152 i+=1
153 return final_data
154
155def parse_list_table(raw_data):
156 i = 1
157 pretty_raw_data = []
158 for datum in raw_data:
159 if datum != "":
160 if datum[3] != ' ' and i > 4:
161 pretty_raw_data.append(raw_data[0])
162 if i == 3:
163 pretty_raw_data.append(datum.replace('-', '='))
164 else:
165 pretty_raw_data.append(datum)
166 i += 1
167 parser = tableparser.GridTableParser()
168 block = statemachine.StringList(pretty_raw_data)
169 docutils_data = parser.parse(block)
170 final_data = []
171 keys = []
172 for line in docutils_data[1]:
173 for item in line:
174 keys.append(' '.join(item[3]).strip())
175 for line in docutils_data[2]:
176 final_line = {}
177 i = 0
178 for item in line:
179 value = ' '.join(item[3]).strip()
180 try:
181 value = json.loads(value)
182 except:
183 pass
184 final_line[keys[i]] = value
185 i += 1
186 final_data.append(final_line)
187 return final_data
188
189def read_table_file(file):
190 table_file = open(file, 'r')
Ales Komarekc000c152016-12-23 15:32:54 +0100191 raw_data = table_file.read().split('\\n')
Ales Komarek0e558ee2016-12-23 13:02:55 +0100192 table_file.close()
193 return raw_data
194
195parser = argparse.ArgumentParser()
196parser.add_argument('-f','--file', help='File with table data', required=True)
197parser.add_argument('-t','--type', help='Type of table (list/item)', required=True)
198args = vars(parser.parse_args())
199
200raw_data = read_table_file(args['file'])
201
202if args['type'] == 'list':
203 final_data = parse_list_table(raw_data)
204else:
205 final_data = parse_item_table(raw_data)
206
207print json.dumps(final_data)
208"""
209 writeFile file: parserFile, text: parserScript
Sergey Kolekonovba203982016-12-21 18:32:17 +0400210 tableFile = "${env.WORKSPACE}/prettytable.txt"
211 writeFile file: tableFile, text: tableStr
Ales Komarekd874d482016-12-26 10:33:29 +0100212
213 cmd = "python ${parserFile} --file '${tableFile}' --type ${type}"
214 if (path) {
Ales Komarekc6d28dd2016-12-28 12:59:38 +0100215 rawData = runVirtualenvCommand(path, cmd)
Ales Komarekd874d482016-12-26 10:33:29 +0100216 }
217 else {
218 rawData = sh (
219 script: cmd,
220 returnStdout: true
221 ).trim()
222 }
Sergey Kolekonovba203982016-12-21 18:32:17 +0400223 data = loadJson(rawData)
224 echo("[Parsed table] ${data}")
225 return data
226}
227
228/**
229 * Install cookiecutter in isolated environment
230 *
231 * @param path Path where virtualenv is created
232 */
233def setupCookiecutterVirtualenv(path) {
234 requirements = [
235 'cookiecutter',
Jakub Josef4df78272017-04-26 14:36:36 +0200236 'jinja2==2.8.1',
237 'PyYAML==3.12'
Sergey Kolekonovba203982016-12-21 18:32:17 +0400238 ]
239 setupVirtualenv(path, 'python2', requirements)
240}
241
242/**
243 * Generate the cookiecutter templates with given context
244 *
Jakub Josef4e10c372017-04-26 14:13:50 +0200245 * @param template template
246 * @param context template context
247 * @param path Path where virtualenv is created (optional)
248 * @param templatePath path to cookiecutter template repo (optional)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400249 */
Jakub Josef4e10c372017-04-26 14:13:50 +0200250def buildCookiecutterTemplate(template, context, outputDir = '.', path = null, templatePath = ".") {
Tomáš Kukráldad7b462017-03-27 13:53:05 +0200251 configFile = "default_config.yaml"
252 configString = "default_context:\n"
Tomáš Kukrál6de85042017-04-12 17:49:05 +0200253 writeFile file: configFile, text: context
Jakub Josef4e61cc02017-04-26 14:29:09 +0200254 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 +0400255 output = sh (returnStdout: true, script: command)
256 echo("[Cookiecutter build] Output: ${output}")
257}
258
259/**
260 * Install jinja rendering in isolated environment
261 *
262 * @param path Path where virtualenv is created
263 */
264def setupJinjaVirtualenv(path) {
265 requirements = [
266 'jinja2-cli',
267 'pyyaml',
268 ]
269 setupVirtualenv(path, 'python2', requirements)
270}
271
272/**
273 * Generate the Jinja templates with given context
274 *
275 * @param path Path where virtualenv is created
276 */
277def jinjaBuildTemplate (template, context, path = none) {
278 contextFile = "jinja_context.yml"
279 contextString = ""
280 for (parameter in context) {
281 contextString = "${contextString}${parameter.key}: ${parameter.value}\n"
282 }
283 writeFile file: contextFile, text: contextString
284 cmd = "jinja2 ${template} ${contextFile} --format=yaml"
285 data = sh (returnStdout: true, script: cmd)
286 echo(data)
287 return data
288}
Oleg Grigorovbec45582017-09-12 20:29:24 +0300289
290/**
291 * Install salt-pepper in isolated environment
292 *
293 * @param path Path where virtualenv is created
294 */
295def setupPepperVirtualenv(path) {
296 requirements = ['salt-pepper']
297 setupVirtualenv(path, 'python2', requirements)
Jakub Josefd067f612017-09-26 13:42:56 +0200298}