Merge "Add test-scheduler dir to verity"
[bottlenecks.git] / test-scheduler / server / src / test_parser.py
1 #!/usr/bin/env python
2
3 ##############################################################################
4 # Copyright (c) 2018 HUAWEI TECHNOLOGIES CO.,LTD and others.
5 #
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 ##############################################################################
11
12 import click
13 import os
14 import yaml
15 import json
16 import collections
17 from src.step.step_manager import TestStepManager
18 from src.conductor_processor.workflow import WorkflowFile
19 from conductorclient.run_new_workflow import WorkflowMgr
20
21 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
22 CONDUCTOR_SERVER_ADDR = "http://conductor_conductor-server_1:8080"
23 STORE_TASK_PATH = "/tmp/generate_task.json"
24 STORE_WF_PATH = "/tmp/generate_workflow.json"
25
26
27 @click.command()
28 @click.option("--filepath", help="file path of test case")
29 def cmdParse(filepath):
30     parse(filepath)
31
32
33 def parse(filepath):
34     filePrefix, fileName = os.path.split(filepath)
35     print '------------ start to parse the test case:' + \
36         '%s ----------------' % fileName
37     with open(filepath) as f:
38         yaml_file = yaml.load(f)
39         parseTestcase(yaml_file['schema'], fileName)
40
41     workflowId = runWorkFlow()
42     print '------------------- parse executes end -------------------------'
43
44     return workflowId
45
46
47 def parseTestcase(schema, tcName='testcase0'):
48     if schema is None:
49         return parseLog(False, reason='schema not found.')
50     steps = schema['steps']
51     if steps is None:
52         return parseLog(False, reason='steps is invalid.')
53     flows = schema['flows']
54     if flows is None:
55         return parseLog(False, reasion='flows is invalid.')
56     # steps is a list, step is dict. no json here.
57     # steps = sorted(steps, sortById)
58
59     # load context
60     contextDict = {}
61     contextDir = os.path.join(BASE_DIR, "env", "context", "context.yaml")
62     with open(contextDir, "r") as f:
63         contextDict = yaml.load(f)
64     #
65     testStepMgr = TestStepManager(contextDict)
66
67     stepObjArr = []
68     for step in steps:
69         if 'args' not in step:
70             step['args'] = {}
71         # type and action can be extended, default couple is 'test' & 'start'.
72         if 'type' not in step:
73             step['type'] = 'test'
74             step['action'] = 'start'
75
76         stepObj = testStepMgr.getStepObj(
77             step['type'], step['id'], step['name'], step['service'],
78             step['action'], step['args'])
79         stepObjArr.append(stepObj)
80
81     # generate workflow by 'flow' and 'step'
82     tcName = os.path.splitext(tcName)[0]
83     wfFileObj = WorkflowFile(tcName)
84     workflowDict, taskMetaList = wfFileObj.generateMetaData(flows, stepObjArr)
85
86     with open(STORE_TASK_PATH, 'w') as f:
87         f.write(json.dumps({'task_group': taskMetaList}, indent=True))
88     with open(STORE_WF_PATH, 'w') as f:
89         f.write(json.dumps(workflowDict, indent=True))
90
91
92 def parseWebTestcase(webTestcase):
93     print 'parseWebTestcase----------------------------'
94
95     stepList = webTestcase['stepList']
96     mainOrdersList = webTestcase['mainOrdersList']
97     subflowList = webTestcase['subflowList']
98
99     parseData = collections.OrderedDict()
100     parseData['schema'] = collections.OrderedDict()
101     parseData['schema']['steps'] = []
102     parseData['schema']['flows'] = []
103
104     parseStepList = parseData['schema']['steps']
105     parseFlowList = parseData['schema']['flows']
106     stepIndexDict = {}
107     # parse stepList
108     for index in range(len(stepList)):
109         stepItem = stepList[index]
110         parseStep = collections.OrderedDict()
111
112         parseStep['id'] = index + 1
113         parseStep['name'] = stepItem['name']
114         parseStep['service'] = collections.OrderedDict()
115         parseStep['service']['name'] = stepItem['service']
116         parseStep['service']['interface'] = stepItem['action']
117         parseStep['action'] = 'start'
118         parseStep['args'] = {}
119         for paramItem in stepItem['params']:
120             parseStep['args'][paramItem['key']] = transParamString(
121                 paramItem['value'])
122
123         parseStepList.append(parseStep)
124         stepIndexDict[parseStep['name']] = parseStep['id']
125     # parse flows
126     # parse mainflow
127     print stepIndexDict
128     typeDict = {1: 'normal', 2: 'switch', 3: 'parallel'}
129     mainFlow = collections.OrderedDict()
130     mainFlow['name'] = 'main'
131     mainFlow['orders'] = []
132     mainFlow['orders'] = parseOrderList(
133         mainOrdersList, stepIndexDict, typeDict)
134     parseFlowList.append(mainFlow)
135
136     # parse subflow
137     for subflowItem in subflowList:
138         replaceSubflow = collections.OrderedDict()
139         replaceSubflow['name'] = subflowItem['name']
140         replaceSubflow['orders'] = parseOrderList(
141             subflowItem['orderList'], stepIndexDict, typeDict)
142         parseFlowList.append(replaceSubflow)
143
144     print 'END parseWebTestcase----------------------------'
145     return parseData
146
147
148 # parse orderlist from web edition to server edition
149 def parseOrderList(orderList, stepIndexDict, typeDict):
150     replaceList = []
151     for orderItem in orderList:
152         replaceOrder = collections.OrderedDict()
153         orderType = typeDict[orderItem['type']]
154         replaceOrder['type'] = orderType
155         if orderType == 'normal':
156             stepId = stepIndexDict[orderItem['step']]
157             replaceOrder['step'] = stepId
158         elif orderType == 'switch':
159             replaceOrder['value'] = orderItem['value']
160             replaceOrder['cases'] = collections.OrderedDict()
161             for caseItem in orderItem['cases']:
162                 caseValue = caseItem['value']
163                 caseOrderType = caseItem['orderType']
164                 caseOrderValue = caseItem['orderValue']
165                 if caseOrderType == "step":
166                     orderInCase = collections.OrderedDict()
167                     orderInCase['type'] = 'normal'
168                     orderInCase['step'] = stepIndexDict[caseOrderValue]
169                     replaceOrder['cases'][caseValue] = [orderInCase]
170                 else:
171                     replaceOrder['cases'][caseValue] = caseOrderValue
172         else:
173             replaceOrder['parallel'] = collections.OrderedDict()
174             pIndex = 1
175             for branchItem in orderItem['branches']:
176                 pKey = 'p' + str(pIndex)
177                 branchOrderType = branchItem['orderType']
178                 branchOrderValue = branchItem['orderValue']
179                 if branchOrderType == "step":
180                     replaceBranchItem = collections.OrderedDict()
181                     replaceBranchItem['type'] = 'normal'
182                     replaceBranchItem['step'] = stepIndexDict[branchOrderValue]
183                     replaceOrder['parallel'][pKey] = [replaceBranchItem]
184                 else:
185                     replaceOrder['parallel'][pKey] = branchOrderValue
186                 pIndex += 1
187         replaceList.append(replaceOrder)
188     return replaceList
189
190
191 def transParamString(val):
192     if type(val) != str:
193         return val
194     if '.' not in val:
195         if val.isdigit():
196             return int(val)
197     try:
198         f = float(val)
199         return f
200     except ValueError:
201         return val
202
203
204 def getWebTestcase(originTcDict):
205     print "getWebTestcase----------------------------------"
206     webTcDict = {
207         "stepList": [],
208         "mainOrdersList": [],
209         "subflowList": []
210     }
211     stepList = webTcDict['stepList']
212     subflowList = webTcDict['subflowList']
213     if originTcDict is None:
214         return webTcDict
215     originContent = originTcDict['schema']
216     originSteps = originContent['steps']
217     stepIndexDict = {}
218     # transform steps to stepList
219     for stepItem in originSteps:
220         replaceStep = {}
221         replaceStep['name'] = stepItem['name']
222         replaceStep['service'] = stepItem['service']['name']
223         replaceStep['action'] = stepItem['service']['interface']
224         replaceStep['params'] = []
225         if 'args' in stepItem:
226             for (key, value) in stepItem['args'].items():
227                 replaceParam = {}
228                 replaceParam['key'] = key
229                 replaceParam['value'] = value
230                 replaceStep['params'].append(replaceParam)
231         stepList.append(replaceStep)
232         stepIndexDict[stepItem['id']] = stepItem['name']
233
234     # transform main flow
235     originFlows = originContent['flows']
236     originMainflow = {}
237     for flowIndex in range(len(originFlows)):
238         flowItem = originFlows[flowIndex]
239         if flowItem['name'] == 'main':
240             originMainflow = flowItem
241             originFlows.pop(flowIndex)
242             break
243     typeDict = {'normal': 1, 'switch': 2, 'parallel': 3}
244     webTcDict['mainOrdersList'] = getOrderList(
245         originMainflow['orders'], stepIndexDict, typeDict)
246
247     # transform subflows
248     for originSubflow in originFlows:
249         replaceSubflow = {}
250         replaceSubflow['name'] = originSubflow['name']
251         replaceSubflow['orderList'] = getOrderList(
252             originSubflow['orders'], stepIndexDict, typeDict)
253         subflowList.append(replaceSubflow)
254
255     # return web edition of testcase
256     print "END getWebTestcase----------------------------------"
257     return webTcDict
258
259
260 def getOrderList(originOrderList, stepIndexDict, typeDict):
261     replaceOrderList = []
262     for orderItem in originOrderList:
263         replaceOrderItem = {}
264         orderType = orderItem['type']
265         replaceOrderItem['type'] = typeDict[orderType]
266         if orderType == 'normal':
267             stepName = stepIndexDict[orderItem['step']]
268             replaceOrderItem['step'] = stepName
269         elif orderType == 'switch':
270             replaceOrderItem['value'] = orderItem['value']
271             replaceOrderItem['cases'] = []
272             for (caseValue, ordersInCase) in orderItem['cases'].items():
273                 replaceCase = {}
274                 replaceCase['value'] = caseValue
275                 if type(ordersInCase) == list:
276                     replaceCase['orderType'] = 'step'
277                     caseStepName = stepIndexDict[ordersInCase[0]['step']]
278                     replaceCase['orderValue'] = caseStepName
279                 else:
280                     replaceCase['orderType'] = 'flow'
281                     replaceCase['orderValue'] = ordersInCase
282                 replaceOrderItem['cases'].append(replaceCase)
283         else:
284             replaceOrderItem['branches'] = []
285             for paraIndex in orderItem['parallel']:
286                 paraItem = orderItem['parallel'][paraIndex]
287                 replaceBranch = {}
288                 if type(paraItem) == list:
289                     replaceBranch['orderType'] = 'step'
290                     branchStepName = stepIndexDict[paraItem[0]['step']]
291                     replaceBranch['orderValue'] = branchStepName
292                 else:
293                     replaceBranch['orderType'] = 'flow'
294                     replaceBranch['orderValue'] = paraItem
295                 replaceOrderItem['branches'].append(replaceBranch)
296         replaceOrderList.append(replaceOrderItem)
297
298     return replaceOrderList
299
300
301 def runWorkFlow():
302     wfMgr = WorkflowMgr(CONDUCTOR_SERVER_ADDR)
303     wfMgr.setTaskDefFromFile(STORE_TASK_PATH)
304     wfMgr.setWorkflowFromFile(STORE_WF_PATH)
305     inputParam = {'input': 'fake'}
306     workflowId = wfMgr.startWorkflow(inputParam)
307     return workflowId
308
309
310 def parseLog(flag, **msg):
311     return {'result': flag, 'message': msg}
312
313
314 if __name__ == "__main__":
315     cmdParse()