fix testsuite name bugs and improve some ui details
[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.yaml'):
48     try:
49         tcName.decode('ascii')
50     except Exception, e:
51         print e
52         tcName = 'testcase0.yaml'
53     if schema is None:
54         return parseLog(False, reason='schema not found.')
55     steps = schema['steps']
56     if steps is None:
57         return parseLog(False, reason='steps is invalid.')
58     flows = schema['flows']
59     if flows is None:
60         return parseLog(False, reasion='flows is invalid.')
61     # steps is a list, step is dict. no json here.
62     # steps = sorted(steps, sortById)
63
64     # load context
65     contextDict = {}
66     contextDir = os.path.join(BASE_DIR, "env", "context", "context.yaml")
67     with open(contextDir, "r") as f:
68         contextDict = yaml.load(f)
69     #
70     testStepMgr = TestStepManager(contextDict)
71
72     stepObjArr = []
73     for step in steps:
74         if 'args' not in step:
75             step['args'] = {}
76         # type and action can be extended, default couple is 'test' & 'start'.
77         if 'type' not in step:
78             step['type'] = 'test'
79             step['action'] = 'start'
80
81         stepObj = testStepMgr.getStepObj(
82             step['type'], step['id'], step['name'], step['service'],
83             step['action'], step['args'])
84         stepObjArr.append(stepObj)
85
86     # generate workflow by 'flow' and 'step'
87     tcName = os.path.splitext(tcName)[0]
88     wfFileObj = WorkflowFile(tcName)
89     workflowDict, taskMetaList = wfFileObj.generateMetaData(flows, stepObjArr)
90
91     with open(STORE_TASK_PATH, 'w') as f:
92         f.write(json.dumps({'task_group': taskMetaList}, indent=True))
93     with open(STORE_WF_PATH, 'w') as f:
94         f.write(json.dumps(workflowDict, indent=True))
95
96
97 def parseWebTestcase(webTestcase):
98     print 'parseWebTestcase----------------------------'
99
100     stepList = webTestcase['stepList']
101     mainOrdersList = webTestcase['mainOrdersList']
102     subflowList = webTestcase['subflowList']
103
104     parseData = collections.OrderedDict()
105     parseData['schema'] = collections.OrderedDict()
106     parseData['schema']['steps'] = []
107     parseData['schema']['flows'] = []
108
109     parseStepList = parseData['schema']['steps']
110     parseFlowList = parseData['schema']['flows']
111     stepIndexDict = {}
112     # parse stepList
113     for index in range(len(stepList)):
114         stepItem = stepList[index]
115         parseStep = collections.OrderedDict()
116
117         parseStep['id'] = index + 1
118         parseStep['name'] = stepItem['name']
119         parseStep['service'] = collections.OrderedDict()
120         parseStep['service']['name'] = stepItem['service']
121         parseStep['service']['interface'] = stepItem['action']
122         parseStep['action'] = 'start'
123         parseStep['args'] = {}
124         for paramItem in stepItem['params']:
125             parseStep['args'][paramItem['key']] = transParamString(
126                 paramItem['value'])
127
128         parseStepList.append(parseStep)
129         stepIndexDict[parseStep['name']] = parseStep['id']
130     # parse flows
131     # parse mainflow
132     print stepIndexDict
133     typeDict = {1: 'normal', 2: 'switch', 3: 'parallel'}
134     mainFlow = collections.OrderedDict()
135     mainFlow['name'] = 'main'
136     mainFlow['orders'] = []
137     mainFlow['orders'] = parseOrderList(
138         mainOrdersList, stepIndexDict, typeDict)
139     parseFlowList.append(mainFlow)
140
141     # parse subflow
142     for subflowItem in subflowList:
143         replaceSubflow = collections.OrderedDict()
144         replaceSubflow['name'] = subflowItem['name']
145         replaceSubflow['orders'] = parseOrderList(
146             subflowItem['orderList'], stepIndexDict, typeDict)
147         parseFlowList.append(replaceSubflow)
148
149     print 'END parseWebTestcase----------------------------'
150     return parseData
151
152
153 # parse orderlist from web edition to server edition
154 def parseOrderList(orderList, stepIndexDict, typeDict):
155     replaceList = []
156     for orderItem in orderList:
157         replaceOrder = collections.OrderedDict()
158         orderType = typeDict[orderItem['type']]
159         replaceOrder['type'] = orderType
160         if orderType == 'normal':
161             stepId = stepIndexDict[orderItem['step']]
162             replaceOrder['step'] = stepId
163         elif orderType == 'switch':
164             replaceOrder['value'] = orderItem['value']
165             replaceOrder['cases'] = collections.OrderedDict()
166             for caseItem in orderItem['cases']:
167                 caseValue = caseItem['value']
168                 caseOrderType = caseItem['orderType']
169                 caseOrderValue = caseItem['orderValue']
170                 if caseOrderType == "step":
171                     orderInCase = collections.OrderedDict()
172                     orderInCase['type'] = 'normal'
173                     orderInCase['step'] = stepIndexDict[caseOrderValue]
174                     replaceOrder['cases'][caseValue] = [orderInCase]
175                 else:
176                     replaceOrder['cases'][caseValue] = caseOrderValue
177         else:
178             replaceOrder['parallel'] = collections.OrderedDict()
179             pIndex = 1
180             for branchItem in orderItem['branches']:
181                 pKey = 'p' + str(pIndex)
182                 branchOrderType = branchItem['orderType']
183                 branchOrderValue = branchItem['orderValue']
184                 if branchOrderType == "step":
185                     replaceBranchItem = collections.OrderedDict()
186                     replaceBranchItem['type'] = 'normal'
187                     replaceBranchItem['step'] = stepIndexDict[branchOrderValue]
188                     replaceOrder['parallel'][pKey] = [replaceBranchItem]
189                 else:
190                     replaceOrder['parallel'][pKey] = branchOrderValue
191                 pIndex += 1
192         replaceList.append(replaceOrder)
193     return replaceList
194
195
196 def transParamString(val):
197     if type(val) != str:
198         return val
199     if '.' not in val:
200         if val.isdigit():
201             return int(val)
202     try:
203         f = float(val)
204         return f
205     except ValueError:
206         return val
207
208
209 def getWebTestcase(originTcDict):
210     print "getWebTestcase----------------------------------"
211     webTcDict = {
212         "stepList": [],
213         "mainOrdersList": [],
214         "subflowList": []
215     }
216     stepList = webTcDict['stepList']
217     subflowList = webTcDict['subflowList']
218     if originTcDict is None:
219         return webTcDict
220     originContent = originTcDict['schema']
221     originSteps = originContent['steps']
222     stepIndexDict = {}
223     # transform steps to stepList
224     for stepItem in originSteps:
225         replaceStep = {}
226         replaceStep['name'] = stepItem['name']
227         replaceStep['service'] = stepItem['service']['name']
228         replaceStep['action'] = stepItem['service']['interface']
229         replaceStep['params'] = []
230         if 'args' in stepItem:
231             for (key, value) in stepItem['args'].items():
232                 replaceParam = {}
233                 replaceParam['key'] = key
234                 replaceParam['value'] = value
235                 replaceStep['params'].append(replaceParam)
236         stepList.append(replaceStep)
237         stepIndexDict[stepItem['id']] = stepItem['name']
238
239     # transform main flow
240     originFlows = originContent['flows']
241     originMainflow = {}
242     for flowIndex in range(len(originFlows)):
243         flowItem = originFlows[flowIndex]
244         if flowItem['name'] == 'main':
245             originMainflow = flowItem
246             originFlows.pop(flowIndex)
247             break
248     typeDict = {'normal': 1, 'switch': 2, 'parallel': 3}
249     webTcDict['mainOrdersList'] = getOrderList(
250         originMainflow['orders'], stepIndexDict, typeDict)
251
252     # transform subflows
253     for originSubflow in originFlows:
254         replaceSubflow = {}
255         replaceSubflow['name'] = originSubflow['name']
256         replaceSubflow['orderList'] = getOrderList(
257             originSubflow['orders'], stepIndexDict, typeDict)
258         subflowList.append(replaceSubflow)
259
260     # return web edition of testcase
261     print "END getWebTestcase----------------------------------"
262     return webTcDict
263
264
265 def getOrderList(originOrderList, stepIndexDict, typeDict):
266     replaceOrderList = []
267     for orderItem in originOrderList:
268         replaceOrderItem = {}
269         orderType = orderItem['type']
270         replaceOrderItem['type'] = typeDict[orderType]
271         if orderType == 'normal':
272             stepName = stepIndexDict[orderItem['step']]
273             replaceOrderItem['step'] = stepName
274         elif orderType == 'switch':
275             replaceOrderItem['value'] = orderItem['value']
276             replaceOrderItem['cases'] = []
277             for (caseValue, ordersInCase) in orderItem['cases'].items():
278                 replaceCase = {}
279                 replaceCase['value'] = caseValue
280                 if type(ordersInCase) == list:
281                     replaceCase['orderType'] = 'step'
282                     caseStepName = stepIndexDict[ordersInCase[0]['step']]
283                     replaceCase['orderValue'] = caseStepName
284                 else:
285                     replaceCase['orderType'] = 'flow'
286                     replaceCase['orderValue'] = ordersInCase
287                 replaceOrderItem['cases'].append(replaceCase)
288         else:
289             replaceOrderItem['branches'] = []
290             for paraIndex in orderItem['parallel']:
291                 paraItem = orderItem['parallel'][paraIndex]
292                 replaceBranch = {}
293                 if type(paraItem) == list:
294                     replaceBranch['orderType'] = 'step'
295                     branchStepName = stepIndexDict[paraItem[0]['step']]
296                     replaceBranch['orderValue'] = branchStepName
297                 else:
298                     replaceBranch['orderType'] = 'flow'
299                     replaceBranch['orderValue'] = paraItem
300                 replaceOrderItem['branches'].append(replaceBranch)
301         replaceOrderList.append(replaceOrderItem)
302
303     return replaceOrderList
304
305
306 def runWorkFlow():
307     wfMgr = WorkflowMgr(CONDUCTOR_SERVER_ADDR)
308     wfMgr.setTaskDefFromFile(STORE_TASK_PATH)
309     wfMgr.setWorkflowFromFile(STORE_WF_PATH)
310     inputParam = {'input': 'fake'}
311     workflowId = wfMgr.startWorkflow(inputParam)
312     return workflowId
313
314
315 def parseLog(flag, **msg):
316     return {'result': flag, 'message': msg}
317
318
319 if __name__ == "__main__":
320     cmdParse()