blob: 1255d0a957494e7dffe1775e7d0e14e772502cd4 [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 */
Vladislav Naumov11103862017-07-19 17:02:39 +030017def setupVirtualenv(path, python = 'python2', reqs = [], reqs_path=null) {
Jakub Josef068f0be2017-04-18 14:34:59 +020018 def virtualenv_cmd = "virtualenv ${path} --python ${python}"
Vladislav Naumov11103862017-07-19 17:02:39 +030019
Sergey Kolekonovba203982016-12-21 18:32:17 +040020 echo("[Python ${path}] Setup ${python} environment")
21 sh(returnStdout: true, script: virtualenv_cmd)
Vladislav Naumov11103862017-07-19 17:02:39 +030022 if (reqs_path==null) {
23 def args = ""
24 for (req in reqs) {
25 args = args + "${req}\n"
26 }
27 writeFile file: "${path}/requirements.txt", text: args
28 reqs_path = "${path}/requirements.txt"
Sergey Kolekonovba203982016-12-21 18:32:17 +040029 }
Vladislav Naumov11103862017-07-19 17:02:39 +030030 runVirtualenvCommand(path, "pip install -r ${reqs_path}")
Sergey Kolekonovba203982016-12-21 18:32:17 +040031}
32
33/**
34 * Run command in specific python virtualenv
35 *
36 * @param path Path to virtualenv
37 * @param cmd Command to be executed
38 */
39def runVirtualenvCommand(path, cmd) {
Jakub Josef0164dc12017-03-28 16:33:46 +020040 virtualenv_cmd = ". ${path}/bin/activate > /dev/null; ${cmd}"
Sergey Kolekonovba203982016-12-21 18:32:17 +040041 echo("[Python ${path}] Run command ${cmd}")
42 output = sh(
43 returnStdout: true,
44 script: virtualenv_cmd
45 ).trim()
46 return output
47}
48
Ales Komarekd874d482016-12-26 10:33:29 +010049
50/**
51 * Install docutils in isolated environment
52 *
53 * @param path Path where virtualenv is created
54 */
55def setupDocutilsVirtualenv(path) {
56 requirements = [
57 'docutils',
58 ]
59 setupVirtualenv(path, 'python2', requirements)
60}
61
62
Sergey Kolekonovba203982016-12-21 18:32:17 +040063@NonCPS
64def loadJson(rawData) {
65 return new groovy.json.JsonSlurperClassic().parseText(rawData)
66}
67
68/**
69 * Parse content from markup-text tables to variables
70 *
71 * @param tableStr String representing the table
72 * @param mode Either list (1st row are keys) or item (key, value rows)
73 * @param format Format of the table
74 */
Ales Komarekd874d482016-12-26 10:33:29 +010075def parseTextTable(tableStr, type = 'item', format = 'rest', path = none) {
Ales Komarek0e558ee2016-12-23 13:02:55 +010076 parserFile = "${env.WORKSPACE}/textTableParser.py"
77 parserScript = """import json
78import argparse
79from docutils.parsers.rst import tableparser
80from docutils import statemachine
81
82def parse_item_table(raw_data):
83 i = 1
84 pretty_raw_data = []
85 for datum in raw_data:
86 if datum != "":
87 if datum[3] != ' ' and i > 4:
88 pretty_raw_data.append(raw_data[0])
89 if i == 3:
90 pretty_raw_data.append(datum.replace('-', '='))
91 else:
92 pretty_raw_data.append(datum)
93 i += 1
94 parser = tableparser.GridTableParser()
95 block = statemachine.StringList(pretty_raw_data)
96 docutils_data = parser.parse(block)
97 final_data = {}
98 for line in docutils_data[2]:
99 key = ' '.join(line[0][3]).strip()
100 value = ' '.join(line[1][3]).strip()
101 if key != "":
102 try:
103 value = json.loads(value)
104 except:
105 pass
106 final_data[key] = value
107 i+=1
108 return final_data
109
110def parse_list_table(raw_data):
111 i = 1
112 pretty_raw_data = []
113 for datum in raw_data:
114 if datum != "":
115 if datum[3] != ' ' and i > 4:
116 pretty_raw_data.append(raw_data[0])
117 if i == 3:
118 pretty_raw_data.append(datum.replace('-', '='))
119 else:
120 pretty_raw_data.append(datum)
121 i += 1
122 parser = tableparser.GridTableParser()
123 block = statemachine.StringList(pretty_raw_data)
124 docutils_data = parser.parse(block)
125 final_data = []
126 keys = []
127 for line in docutils_data[1]:
128 for item in line:
129 keys.append(' '.join(item[3]).strip())
130 for line in docutils_data[2]:
131 final_line = {}
132 key = ' '.join(line[0][3]).strip()
133 value = ' '.join(line[1][3]).strip()
134 if key != "":
135 try:
136 value = json.loads(value)
137 except:
138 pass
139 final_data[key] = value
140 i+=1
141 return final_data
142
143def parse_list_table(raw_data):
144 i = 1
145 pretty_raw_data = []
146 for datum in raw_data:
147 if datum != "":
148 if datum[3] != ' ' and i > 4:
149 pretty_raw_data.append(raw_data[0])
150 if i == 3:
151 pretty_raw_data.append(datum.replace('-', '='))
152 else:
153 pretty_raw_data.append(datum)
154 i += 1
155 parser = tableparser.GridTableParser()
156 block = statemachine.StringList(pretty_raw_data)
157 docutils_data = parser.parse(block)
158 final_data = []
159 keys = []
160 for line in docutils_data[1]:
161 for item in line:
162 keys.append(' '.join(item[3]).strip())
163 for line in docutils_data[2]:
164 final_line = {}
165 i = 0
166 for item in line:
167 value = ' '.join(item[3]).strip()
168 try:
169 value = json.loads(value)
170 except:
171 pass
172 final_line[keys[i]] = value
173 i += 1
174 final_data.append(final_line)
175 return final_data
176
177def read_table_file(file):
178 table_file = open(file, 'r')
Ales Komarekc000c152016-12-23 15:32:54 +0100179 raw_data = table_file.read().split('\\n')
Ales Komarek0e558ee2016-12-23 13:02:55 +0100180 table_file.close()
181 return raw_data
182
183parser = argparse.ArgumentParser()
184parser.add_argument('-f','--file', help='File with table data', required=True)
185parser.add_argument('-t','--type', help='Type of table (list/item)', required=True)
186args = vars(parser.parse_args())
187
188raw_data = read_table_file(args['file'])
189
190if args['type'] == 'list':
191 final_data = parse_list_table(raw_data)
192else:
193 final_data = parse_item_table(raw_data)
194
195print json.dumps(final_data)
196"""
197 writeFile file: parserFile, text: parserScript
Sergey Kolekonovba203982016-12-21 18:32:17 +0400198 tableFile = "${env.WORKSPACE}/prettytable.txt"
199 writeFile file: tableFile, text: tableStr
Ales Komarekd874d482016-12-26 10:33:29 +0100200
201 cmd = "python ${parserFile} --file '${tableFile}' --type ${type}"
202 if (path) {
Ales Komarekc6d28dd2016-12-28 12:59:38 +0100203 rawData = runVirtualenvCommand(path, cmd)
Ales Komarekd874d482016-12-26 10:33:29 +0100204 }
205 else {
206 rawData = sh (
207 script: cmd,
208 returnStdout: true
209 ).trim()
210 }
Sergey Kolekonovba203982016-12-21 18:32:17 +0400211 data = loadJson(rawData)
212 echo("[Parsed table] ${data}")
213 return data
214}
215
216/**
217 * Install cookiecutter in isolated environment
218 *
219 * @param path Path where virtualenv is created
220 */
221def setupCookiecutterVirtualenv(path) {
222 requirements = [
223 'cookiecutter',
Jakub Josef4df78272017-04-26 14:36:36 +0200224 'jinja2==2.8.1',
225 'PyYAML==3.12'
Sergey Kolekonovba203982016-12-21 18:32:17 +0400226 ]
227 setupVirtualenv(path, 'python2', requirements)
228}
229
230/**
231 * Generate the cookiecutter templates with given context
232 *
Jakub Josef4e10c372017-04-26 14:13:50 +0200233 * @param template template
234 * @param context template context
235 * @param path Path where virtualenv is created (optional)
236 * @param templatePath path to cookiecutter template repo (optional)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400237 */
Jakub Josef4e10c372017-04-26 14:13:50 +0200238def buildCookiecutterTemplate(template, context, outputDir = '.', path = null, templatePath = ".") {
Tomáš Kukráldad7b462017-03-27 13:53:05 +0200239 configFile = "default_config.yaml"
240 configString = "default_context:\n"
Tomáš Kukrál6de85042017-04-12 17:49:05 +0200241 writeFile file: configFile, text: context
Jakub Josef4e61cc02017-04-26 14:29:09 +0200242 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 +0400243 output = sh (returnStdout: true, script: command)
244 echo("[Cookiecutter build] Output: ${output}")
245}
246
247/**
248 * Install jinja rendering in isolated environment
249 *
250 * @param path Path where virtualenv is created
251 */
252def setupJinjaVirtualenv(path) {
253 requirements = [
254 'jinja2-cli',
255 'pyyaml',
256 ]
257 setupVirtualenv(path, 'python2', requirements)
258}
259
260/**
261 * Generate the Jinja templates with given context
262 *
263 * @param path Path where virtualenv is created
264 */
265def jinjaBuildTemplate (template, context, path = none) {
266 contextFile = "jinja_context.yml"
267 contextString = ""
268 for (parameter in context) {
269 contextString = "${contextString}${parameter.key}: ${parameter.value}\n"
270 }
271 writeFile file: contextFile, text: contextString
272 cmd = "jinja2 ${template} ${contextFile} --format=yaml"
273 data = sh (returnStdout: true, script: cmd)
274 echo(data)
275 return data
276}