def createTestartifact(postRequest: POSTTestartifacts): """ Creates Testartifacts for a Project """ r = Response() try: # --------------------------------------| # GET/UPDATE RELATED DATA if not isinstance(postRequest.project_id, int): r = Response(response=f"Invalid Id: {postRequest.project_id}", status='422', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r project = getProject(postRequest.project_id) if not project: r = Response( response=f"No project with Id: {postRequest.project_id}", status='404', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r project.status = 'TAGENERATED' updateProject(project) # --------------------------------------| # OBJECT CREATION testartifact = Testartifact( status=project.status, project_id=project.id, ) databaseSession.add(testartifact) databaseSession.flush() # --------------------------------------| # GENERATE OPERATION generate.run(project, testartifact) # --------------------------------------| newTestartifact = dbtestartifacts.getTestartifactForProject( project, True) r = Response(response=json.dumps(newTestartifact.to_dict()), status='201', mimetype="application/json") r.headers["Content-Type"] = "application/json; charset=utf-8" databaseSession.commit() except: databaseSession.rollback() raise finally: databaseSession.remove() return r
def createProject(postRequest: POSTProjects): """ Handler function to create a new Project. Creates a new Project and initializes the project directory. It does this by cloning the repository specified in the request to the general project directory specified in the radonCTTConfig """ r = Response() if not postRequest.repository_url: r = Response(response='No repository url specified', status='422', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r if not postRequest.servicetemplate_location: r = Response(response='No servicetemplate location specified', status='422', mimetype='text/xml') r.headers['Content-Type'] = 'text/xml; charset=utf-8' return r try: # --------------------------------------| # OBJECT CREATION newProject = Project( status='WAITING', repository_url=postRequest.repository_url, servicetemplate_location=postRequest.servicetemplate_location, project_path='NaN') databaseSession.add(newProject) databaseSession.flush() # --------------------------------------| # IMPORT OPERATION importation.run(newProject) # --------------------------------------| r = Response(response=json.dumps(newProject.to_dict()), status='201', mimetype="text/json") r.headers["Content-Type"] = "application/json; charset=utf-8" databaseSession.commit() except: databaseSession.rollback() raise finally: databaseSession.remove() return r
def generatePolicyTest(project, testartifact, policy): """ This is a policy generator function for the loadTest performance policy type. It creates a PolicyTest to represent the performance policy and then calls node generator functions. Args: - project (Project): The Project you wish to generate testartifacts for - testartifact (Testartifact): The Testartifact object to use for test generation - policy (Dict) : This policies representation in the servicetemplate """ # Define the node generator function layer functionSwitch = { # ################################################################# # NODE TYPES ARE MAPPED TO NODE GENERATOR FUNCTIONS HERE # ################################################################# # WebApplication 'radon.nodes.docker.WebApplication': webApplication.generateNodeTest } #Create the PolicyTest resource representing this performance policy policyTest = PolicyTest(status=project.status, project_id=project.id, testartifact_id=testartifact.id, policy=json.dumps(policy)) databaseSession.add(policyTest) databaseSession.flush() #Generate a directory for the PolicyTest directory = os.path.dirname( f"{project.project_path}testartifacts{os.path.sep}{policyTest.id}{os.path.sep}" ) if not os.path.exists(directory): os.makedirs(directory) #Call a node generator function for every node targeted by this performance policy for nodeName in parser.getNodeTemplates(): node = parser.getNodeTemplates().get(nodeName) if (node['type'] in functionSwitch) and (nodeName in policy['targets'][0]): nodeGeneratorFunc = functionSwitch[node['type']] nodeGeneratorFunc(project, testartifact, policyTest, policy, node)
def generatePolicyTest(project, testartifact, policy): """ This is a >>>TERMINAL<<< generator function -> This is a policy generator function for the shellScript custom policy type. It creates a PolicyTest to represent the custom policy. It does not go any deeper in the generator function layers. Args: - project (Project): The Project you wish to generate testartifacts for - testartifact (Testartifact): The Testartifact object to use for test generation - policy (Dict) : This policies representation in the servicetemplate """ #Create the PolicyTest resource representing this performance policy policyTest = PolicyTest(status=project.status, project_id=project.id, testartifact_id=testartifact.id, policy=json.dumps(policy)) databaseSession.add(policyTest) databaseSession.flush()
def createDeployment(postRequest: POSTDeployments): r = Response() try: # --------------------------------------| # GET/UPDATE RELATED DATA if not isinstance(postRequest.testartifact_id, int): r = Response(response='{}{}'.format('Invalid Id: ', postRequest.testartifact_id), status='422', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r testartifact = getTestartifact(postRequest.testartifact_id, True) if not testartifact: r = Response(response='{}{}'.format('No testartifact with Id: ', postRequest.testartifact_id), status='404', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r project = getProject(testartifact.project_id) if not project: r = Response(response='{}{}'.format('No project with Id: ', testartifact.project_id), status='404', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r testartifact.status = 'DEPLOYED' project.status = 'DEPLOYED' updateTestartifact(testartifact) updateProject(project) # --------------------------------------| # OBJECT CREATION deployment = Deployment( status='DEPLOYED', project_id=project.id, testartifact_id=testartifact.id, ) databaseSession.add(deployment) databaseSession.flush() # --------------------------------------| # DEPLOY OPERATION deploy.run(project, testartifact) # --------------------------------------| r = Response(response=json.dumps(deployment.to_dict()), status='201', mimetype="application/json") r.headers["Content-Type"] = "application/json; charset=utf-8" databaseSession.commit() except: databaseSession.rollback() raise finally: databaseSession.remove() return r
def createExecutor(postRequest: POSTExecutors): r = Response() try: # --------------------------------------| # GET/UPDATE RELATED DATA if not isinstance(postRequest.deployment_id, int): r = Response(response='{}{}'.format('Invalid Id: ', postRequest.deployment_id), status='422', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r deployment = getDeployment(postRequest.deployment_id) if not deployment: r = Response(response='{}{}'.format('No deployment with Id: ', postRequest.deployment_id), status='404', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r testartifact = getTestartifact(deployment.testartifact_id, True) if not testartifact: r = Response(response='{}{}'.format('No testartifact with Id: ', deployment.testartifact_id), status='404', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r project = getProject(deployment.project_id) if not project: r = Response(response='{}{}'.format('No project with Id: ', deployment.project_id), status='404', mimetype="text/xml") r.headers["Content-Type"] = "text/xml; charset=utf-8" return r project.status = 'EXECUTED' testartifact.status = 'EXECUTED' deployment.status = 'EXECUTED' updateProject(project) updateTestartifact(testartifact) updateDeployment(deployment) # --------------------------------------| # OBJECT CREATION executor = Executor( status='EXECUTED', project_id=project.id, deployment_id=deployment.id, ) databaseSession.add(executor) databaseSession.flush() result = Result( project_id=project.id, testartifact_id=testartifact.id, result_path=f"{project.project_path}results{os.path.sep}report.csv", ) databaseSession.add(result) databaseSession.flush() # --------------------------------------| # EXECUTE OPERATION execute.run(project, deployment, testartifact) # --------------------------------------| # EVALUATE OPERATION evaluate.run(project, testartifact, result) # --------------------------------------| r = Response(response=json.dumps(result.to_dict()), status='201', mimetype="application/json") r.headers["Content-Type"] = "application/json; charset=utf-8" databaseSession.commit() except: databaseSession.rollback() raise finally: databaseSession.remove() return r
def generateTestForPolicyAverageResponseTimeRunnerPythonEventObjectCreated(project, testartifact, policyTest, policy, node): """ This is a >>>TERMINAL<<< generator function for the lambdaFunction node type and the averageReponseTime policy and the python runner and the object created event. It copies the related template and fills it with parameters from the policy and node. Args: - project (Project): The Project you wish to generate this NodeTest for - testartifact (Testartifact): The Testartifact object to use for test generation - policyTest (PolicyTest) : The PolicyTest responsible for this NodeTest - policy (Dict) : The policy represantation in the servicetemplate - node (Dict) : This nodes represantation in the servicetemplate """ #Create a NodeTest to represent this node nodeTest = NodeTest( status= project.status, project_id= project.id, policy_test_id= policyTest.id, node = json.dumps(node), artifact_path= '', ) databaseSession.add(nodeTest) databaseSession.flush() #Set the path this NodeTests artifacts will be placed in nodeTest.artifact_path = f"{project.project_path}testartifacts{os.path.sep}{policyTest.id}{os.path.sep}{nodeTest.id}{os.path.sep}" updateNodeTest(nodeTest) # Generate the NodeTests artifact directory directory = os.path.dirname(nodeTest.artifact_path) if not os.path.exists(directory): os.makedirs(directory) #Get the template parameters from the policy and node # +++TEMPLATE PARAMETERS+++ # ARG 1 : REPEATS # ARG 2 : FUNCTION_NAME # ARG 3 : SOURCE_FILE_PREFIX # ARG 4 : SOURCE_FILE_POSTFIX # ARG 5 : BUCKET_NAME # ARG 6 : SOURCE_FILE_PATH # ARG 7 : RESULT_PATH # ARG 8 : UNIQUE_TEST_ID # +++++++++++++++++++++++++ repeats = f"{policy['properties']['repeats']}" function_name = f"{node['properties']['function_name']}" source_file_prefix = f"{node['properties']['trigger_file_prefix']}" source_file_postfix = f"{node['properties']['trigger_file_postfix']}" bucket_name = f"{node['properties']['trigger_bucket_name']}" source_file_path = f"{project.project_path}{source_file_prefix}{source_file_postfix}" result_path = f"{nodeTest.artifact_path}" unique_test_id = f"{nodeTest.id}" # We need the absolute path to the template templatePath = f"{os.getcwd()}{os.path.sep}radonCTT{os.path.sep}templates{os.path.sep}averageResponseTime{os.path.sep}aws{os.path.sep}lambdaFunction{os.path.sep}python-object-create{os.path.sep}" # Copy the template into our NodeTest artifact directory distutils.dir_util.copy_tree(templatePath, nodeTest.artifact_path) # Fill the absolute path to the python runner into the python playbook and call with our arguments playbookPath = f"{nodeTest.artifact_path}artifacts{os.path.sep}create.yml" pythonRunnerPath = f"{nodeTest.artifact_path}artifacts{os.path.sep}run.py" pythonRunCommand = f"{pythonRunnerPath} {repeats} {function_name} {source_file_prefix} {source_file_postfix} {bucket_name} {source_file_path} {result_path} {unique_test_id}" # Read and edit with open(playbookPath) as instream: try: playbook = yaml.safe_load(instream) playbook[0]['tasks'][0]['script'] = pythonRunCommand except yaml.YAMLError as exc: print(exc) # Push edits with open(playbookPath, "w") as outstream: try: yaml.dump(playbook, outstream) except yaml.YAMLError as exc: print(exc)
def generateTestForPolicyLoadTestRunnerJmeter(project, testartifact, policyTest, policy, node): """ This is a >>>TERMINAL<<< generator function for the WebApplication node type and the loadTest policy and the jmeter runner. Args: - project (Project): The Project you wish to generate this NodeTest for - testartifact (Testartifact): The Testartifact object to use for test generation - policyTest (PolicyTest) : The PolicyTest responsible for this NodeTest - policy (Dict) : The policy represantation in the servicetemplate - node (Dict) : This nodes represantation in the servicetemplate """ #Create a NodeTest to represent this node nodeTest = NodeTest( status=project.status, project_id=project.id, policy_test_id=policyTest.id, node=json.dumps(node), artifact_path='', ) databaseSession.add(nodeTest) databaseSession.flush() #Set the path this NodeTests artifacts will be placed in nodeTest.artifact_path = f"{project.project_path}testartifacts{os.path.sep}{policyTest.id}{os.path.sep}{nodeTest.id}{os.path.sep}" updateNodeTest(nodeTest) # Generate the NodeTests artifact directory directory = os.path.dirname(nodeTest.artifact_path) if not os.path.exists(directory): os.makedirs(directory) #Get information from the policy and node to create the testplan from a template # +++TEMPLATE PARAMETERS+++ # 1 : THREADS # 2 : REPEATS # 3 : UPPER_BOUND # 4 : HOST # 5 : PORTS # +++++++++++++++++++++++++ threads = f"{policy['properties']['threads']}" repeats = f"{policy['properties']['repeats']}" upper_bound = f"{policy['properties']['upper_bound']}" host = f"{node['properties']['host']}" ports = node.get('properties').get('ports') # We need the absolute path to the testplan template to copy it templatePath = f"{os.getcwd()}{os.path.sep}radonCTT{os.path.sep}templates{os.path.sep}loadTest{os.path.sep}webApplication{os.path.sep}jmeter-load-test{os.path.sep}" # Copy the testplan template into our NodeTest artifact directory distutils.dir_util.copy_tree(templatePath, nodeTest.artifact_path) # Fill the absolute path to the testplan into the playbook and call with our arguments playbookPath = f"{nodeTest.artifact_path}artifacts{os.path.sep}create.yml" testplanPath = f"{nodeTest.artifact_path}artifacts{os.path.sep}testplan.jmx" jmeterRunCommand = f"jmeter -n -t {testplanPath} -l {nodeTest.artifact_path}result.csv" # <<<<<<<<<<<<<<<<< PLAY BOOK EDITING >>>>>>>>>>>>>>>>> # Read and edit with open(playbookPath) as instream: try: playbook = yaml.safe_load(instream) playbook[0]['tasks'][0]['shell'] = jmeterRunCommand except yaml.YAMLError as exc: print(exc) # Push edits with open(playbookPath, "w") as outstream: try: yaml.dump(playbook, outstream) except yaml.YAMLError as exc: print(exc) # <<<<<<<<<<<<<<<<< TEST PLAN EDITING >>>>>>>>>>>>>>>>> tree = ET.parse(testplanPath) root = tree.getroot() # Write metadata to the testplan threadGroupHashTree = root[0][1] threadGroup = threadGroupHashTree[0] threadGroupController = threadGroup[1] subThreadGroupHashTree = threadGroupHashTree[1] durationAssertion = subThreadGroupHashTree[0] subThreadGroupHashTreeSeparator = subThreadGroupHashTree[1] httpSampler = subThreadGroupHashTree[2] # DURATION durationAssertionDuration = durationAssertion[0] durationAssertionDuration.text = upper_bound # LOOPS loopController = threadGroupController[1] loopController.text = repeats # THREADS threadGroupNumThreads = threadGroup[2] threadGroupNumThreads.text = threads # Create Samplers for every pathill NodeTestAverages into the list isFirstHttpSampler = True for port in ports: paths = ports.get(port) for path in paths: if isFirstHttpSampler: newHttpSampler = httpSampler else: newHttpSampler = copy.deepcopy(httpSampler) newSeparator = copy.deepcopy(subThreadGroupHashTreeSeparator) #Set the values in the HTTP Sampler httpSamplerHost = newHttpSampler[1] httpSamplerPort = newHttpSampler[2] httpSamplerPath = newHttpSampler[7] httpSamplerHost.text = f"{host}" httpSamplerPort.text = f"{port}" httpSamplerPath.text = f"{path}" if isFirstHttpSampler: isFirstHttpSampler = False else: subThreadGroupHashTree.append(newHttpSampler) subThreadGroupHashTree.append(newSeparator) #Write the changes to the file tree.write(testplanPath)