def test_executionDetails_emptyExecution(self) : s = self.emptyExecution() w = ExecutionDetails() s = Server("fixture") content = w.generate(s,"myproject","myclient","20130301-232425") self.assertMultiLineEqual( content, """\ <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="utf-8"> <title>TestFarm: Execution details for myproject :: myclient :: 20130301-232425</title> <style> """+deansi.styleSheet() + """ </style> <link href="style.css" rel="stylesheet" type="text/css"> <script type="text/javascript" language="JavaScript" src="testfarm.js"></script> </head> <body> <h1>Details for execution '20130301-232425'</h1> <div class='execution'> <p>Started at 2013-03-01 23:24:25</p> <p>Execution '20130301-232425' finalized with a <b>SUCCESS</b></p> </div> <div class="about"> <p>TestFarm is free software. Learn <a href="http://testfarm.sf.net/">about TestFarm</a>.</p> </div> </body> </html> """)
def test_executionDetails_emptyExecution(self) : s = self.emptyExecution() w = ExecutionDetails() s = Logger("fixture") content = w.generate(s,"myproject","myclient","20130301-232425") self.assertMultiLineEqual( content, """\ <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="utf-8"> <title>TestFarm: Execution details for myproject :: myclient :: 20130301-232425</title> <style> """+deansi.styleSheet() + """ </style> <link href="style.css" rel="stylesheet" type="text/css"> <script type="text/javascript" language="JavaScript" src="testfarm.js"></script> </head> <body> <h1>Details for execution '20130301-232425'</h1> <div class='execution'> <p>Started at 2013-03-01 23:24:25</p> <p>Execution '20130301-232425' finalized with a <b>SUCCESS</b></p> </div> <div class="about"> <p>TestFarm is free software. Learn <a href="http://testfarm.sf.net/">about TestFarm</a>.</p> </div> </body> </html> """)
def generate(self, logger, project, client, execution): executionSummary = logger.execution(project, client, execution) executionInfo = logger.executionInfo(project, client, execution) return self.template.format( project=project, client=client, execution=execution, deansi_style=deansi.styleSheet(), content=ExecutionDetails().execution(executionSummary), )
def generate(self, server, project, client, execution) : executionSummary = server.execution(project, client, execution) executionInfo = server.executionInfo(project, client, execution) return self.template.format( project = project, client = client, execution = execution, deansi_style = deansi.styleSheet(), content = ExecutionDetails().execution(executionSummary), )
def END_TASK(task_name, end_time, status) : if f.opened_cmd: #assert f.opened_task #assert f.opened_subtask f.content.append( '<span class="command_failure">[FAILURE]</span>' ) f.content.append( '<p class="output"> command execution aborted by the client</p>') f.content.append('</div>') if f.opened_subtask: #assert f.opened_task f.content.append('</div>') f.content.append( 'END_TASK "%s" %s %s</div>' % (task_name, end_time, status) ) #exiting, so no need to make f.opened_task=False return header_details%dict(deansi_style=deansi.styleSheet()) + '\n'.join(f.content) + footer
def runner(cmd): scripts = configScripts() script=scripts[cmd] script.islist = type(script.script) is list if 'parameters' in script: for parm in script.parameters: if ("type" in script.parameters[parm] and script.parameters[parm].type == "FILEDOWN"): script=parseDownloadFileParm( parm,script) return render_template( 'runner_template.html', name=cmd, style=deansi.styleSheet(), **script )
def run(self): start_time = time.time() branch = self.context.source['branch'] context = { 'context': self.context, 'build_log_url': self.build_status.url, 'branch': branch['name'], 'scripts': self.spec.scripts, 'ansi_termcolor_style': deansi.styleSheet(), } self.update_build_status('INPROGRESS', 'Test in progress') docker_image_name, build_output = self.get_docker_image() context.update({ 'build_logs': Markup(build_output), 'elapsed_time': int(time.time() - start_time), }) if not docker_image_name: self.update_build_status('FAILED', 'Build or get Docker image failed') context['exit_code'] = -1 self.send_notifications(context) return exit_code, output = self.run_in_container(docker_image_name) logger.debug('Docker run output: %s', output) if exit_code == 0: # Success logger.info('Test succeed for repo: %s', self.context.repository) self.update_build_status('SUCCESSFUL', '1 of 1 test succeed') else: # Failed logger.info('Test failed for repo: %s, exit code: %s', self.context.repository, exit_code) if exit_code == 137: self.update_build_status('FAILED', 'build cancelled') else: self.update_build_status('FAILED', '1 of 1 test failed') context.update({ 'logs': Markup(deansi.deansi(output)), 'exit_code': exit_code, 'elapsed_time': int(time.time() - start_time), }) self.send_notifications(context) return exit_code == 0
def _streaming_gen(): yield '<style>{}</style>'.format(deansi.styleSheet()) yield FOLLOW_LOG_JS yield '<div class="ansi_terminal">' buffer = [] for log in container.logs(stdout=True, stderr=True, stream=True, follow=True): char = str(log) buffer.append(char) if char == '\n': yield deansi.deansi(''.join(buffer)) buffer = [] if buffer: yield deansi.deansi(''.join(buffer)) yield '</div>'
def END_TASK(task_name, end_time, status): if f.opened_cmd: #assert f.opened_task #assert f.opened_subtask f.content.append( '<span class="command_failure">[FAILURE]</span>') f.content.append( '<p class="output"> command execution aborted by the client</p>' ) f.content.append('</div>') if f.opened_subtask: #assert f.opened_task f.content.append('</div>') f.content.append('END_TASK "%s" %s %s</div>' % (task_name, end_time, status)) #exiting, so no need to make f.opened_task=False return header_details % dict( deansi_style=deansi.styleSheet()) + '\n'.join( f.content) + footer
def __html_single_execution_details(self, client_name, wanted_date): "Creates an HTML file with the details of an execution given a date" class Namespace(): pass f = Namespace( ) # so that inner functions can modify the following vars f.content = [] f.id_info = 1 f.id_output = 1 f.opened_task = False f.opened_subtask = False f.opened_cmd = False def BEGIN_TASK(taskname, begin_date): #assert not f.opened_task #assert not f.opened_subtask #assert not f.opened_cmd f.content.append('<div class="task"> BEGIN_TASK "%s" %s' % (taskname, begin_date)) f.opened_task = True def BEGIN_SUBTASK(subtaskname): #assert f.opened_task #assert not f.opened_subtask #assert not f.opened_cmd subtask_name = entry[1] f.content.append('<div class="subtask"> BEGIN_SUBTASK "%s"' % subtaskname) f.opened_subtask = True def BEGIN_CMD(command): #assert f.opened_task #assert f.opened_subtask #assert not f.opened_cmd f.content.append('<div class=command>') f.content.append('<span class="command_string"> %s</span>' % command) f.opened_cmd = True def END_SUBTASK(subtask_name): #assert f.opened_task #assert f.opened_subtask #assert not f.opened_cmd f.content.append('END_SUBTASK "%s"</div>' % subtask_name) f.opened_subtask = False def END_TASK(task_name, end_time, status): if f.opened_cmd: #assert f.opened_task #assert f.opened_subtask f.content.append( '<span class="command_failure">[FAILURE]</span>') f.content.append( '<p class="output"> command execution aborted by the client</p>' ) f.content.append('</div>') if f.opened_subtask: #assert f.opened_task f.content.append('</div>') f.content.append('END_TASK "%s" %s %s</div>' % (task_name, end_time, status)) #exiting, so no need to make f.opened_task=False return header_details % dict( deansi_style=deansi.styleSheet()) + '\n'.join( f.content) + footer def END_CMD(command, ok, output, info, stats): #assert f.opened_task #assert f.opened_subtask #assert f.opened_cmd if ok: f.content.append('<span class="command_ok">[OK]</span>') else: f.content.append( '<span class="command_failure">[FAILURE]</span>') f.content.append('<div id="output%d" class="output">' '<div class="output_header">OUTPUT:</div>' '<div class="plain_text">%s</div>' '</div>' % (f.id_output, deansi.deansi(output))) if output.count('\n') > 10: f.content.append( '<script type="text/javascript">togglesize(\'output%d\');</script>' % f.id_output) f.id_output += 1 if info: f.content.append('<div id="info%d" class="info">' '<div class="info_header">INFO:</div>\n' '<div class="plain_text">%s</div></div>' % (f.id_info, deansi.deansi(info))) if info.count('\n') > 10: f.content.append( '<script type="text/javascript">togglesize(\'info%d\');</script>' % f.id_info) f.id_info += 1 if stats: f.content.append('<div class="stats_header">Statistics:</div>' '<div class="stats">' + '<br />'.join([ '<b>%s:</b> %s' % (item) for item in stats.iteritems() ]) + '</div>') f.content.append('</div>') f.opened_cmd = False for entry in self.single_execution_details(client_name, wanted_date): tag = entry[0].strip() assert tag in [ 'BEGIN_TASK', 'END_TASK', 'BEGIN_SUBTASK', 'END_SUBTASK', 'BEGIN_CMD', 'END_CMD', ], 'Log Parsing Error. Bad entry tag: "%s"' % tag locals()[tag](*entry[1:]) if f.opened_cmd: f.content.append( '<span class="command_inprogress">in progress ...</span>') f.content.append('</div>') if f.opened_subtask: f.content.append('</div>') if f.opened_task: f.content.append('</div>') return header_details % dict( deansi_style=deansi.styleSheet()) + '\n'.join(f.content) + footer
def __html_single_execution_details(self, client_name, wanted_date): "Creates an HTML file with the details of an execution given a date" class Namespace() : pass f=Namespace() # so that inner functions can modify the following vars f.content = [] f.id_info = 1 f.id_output = 1 f.opened_task = False f.opened_subtask = False f.opened_cmd = False def BEGIN_TASK(taskname, begin_date) : #assert not f.opened_task #assert not f.opened_subtask #assert not f.opened_cmd f.content.append('<div class="task"> BEGIN_TASK "%s" %s' % (taskname, begin_date) ) f.opened_task = True def BEGIN_SUBTASK(subtaskname) : #assert f.opened_task #assert not f.opened_subtask #assert not f.opened_cmd subtask_name = entry[1] f.content.append('<div class="subtask"> BEGIN_SUBTASK "%s"' % subtaskname ) f.opened_subtask = True def BEGIN_CMD(command) : #assert f.opened_task #assert f.opened_subtask #assert not f.opened_cmd f.content.append( '<div class=command>' ) f.content.append( '<span class="command_string"> %s</span>' % command ) f.opened_cmd = True def END_SUBTASK(subtask_name) : #assert f.opened_task #assert f.opened_subtask #assert not f.opened_cmd f.content.append('END_SUBTASK "%s"</div>' % subtask_name) f.opened_subtask = False def END_TASK(task_name, end_time, status) : if f.opened_cmd: #assert f.opened_task #assert f.opened_subtask f.content.append( '<span class="command_failure">[FAILURE]</span>' ) f.content.append( '<p class="output"> command execution aborted by the client</p>') f.content.append('</div>') if f.opened_subtask: #assert f.opened_task f.content.append('</div>') f.content.append( 'END_TASK "%s" %s %s</div>' % (task_name, end_time, status) ) #exiting, so no need to make f.opened_task=False return header_details%dict(deansi_style=deansi.styleSheet()) + '\n'.join(f.content) + footer def END_CMD(command, ok, output, info, stats) : #assert f.opened_task #assert f.opened_subtask #assert f.opened_cmd if ok : f.content.append( '<span class="command_ok">[OK]</span>' ) else: f.content.append( '<span class="command_failure">[FAILURE]</span>' ) f.content.append( '<div id="output%d" class="output">' '<div class="output_header">OUTPUT:</div>' '<div class="plain_text">%s</div>' '</div>' % (f.id_output, deansi.deansi(output) ) ) if output.count('\n') > 10 : f.content.append( '<script type="text/javascript">togglesize(\'output%d\');</script>' % f.id_output ) f.id_output += 1 if info : f.content.append( '<div id="info%d" class="info">' '<div class="info_header">INFO:</div>\n' '<div class="plain_text">%s</div></div>' % ( f.id_info, deansi.deansi(info) ) ) if info.count('\n') > 10 : f.content.append( '<script type="text/javascript">togglesize(\'info%d\');</script>' % f.id_info ) f.id_info += 1 if stats : f.content.append( '<div class="stats_header">Statistics:</div>' '<div class="stats">' + '<br />'.join(['<b>%s:</b> %s'%(item) for item in stats.iteritems() ]) + '</div>' ) f.content.append( '</div>' ) f.opened_cmd = False for entry in self.single_execution_details(client_name, wanted_date ): tag = entry[0].strip() assert tag in [ 'BEGIN_TASK', 'END_TASK', 'BEGIN_SUBTASK', 'END_SUBTASK', 'BEGIN_CMD', 'END_CMD', ], 'Log Parsing Error. Bad entry tag: "%s"' % tag locals()[tag](*entry[1:]) if f.opened_cmd : f.content.append( '<span class="command_inprogress">in progress ...</span>' ) f.content.append( '</div>') if f.opened_subtask : f.content.append( '</div>') if f.opened_task : f.content.append( '</div>') return header_details%dict(deansi_style=deansi.styleSheet()) + '\n'.join(f.content) + footer
def sendMail( sender, to, subject, text=None, html=None, md=None, ansi=None, cc=[], bcc=[], replyto=[], attachments = [], template=None, config=None, stylesheets = [], dump = None, verbose=True ): import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email.mime.text import MIMEText from email.encoders import encode_base64 from email.utils import formataddr, parseaddr if not config: from config import smtp else: import imp smtp=imp.load_source('config',config).smtp def formatAddress(address): return formataddr(parseaddr(address)) def formatAddresses(addresses): return ', '.join(formatAddress(a) for a in addresses) # Headers msg = MIMEMultipart() msg['Subject'] = subject msg['From'] = formatAddress(sender) msg['To'] = formatAddresses(to) if cc: msg['CC'] = formatAddresses(cc) if bcc: msg['BCC'] = formatAddresses(bcc) if replyto: msg['Reply-To'] = formatAddresses(replyto) recipients = to + (cc if cc else []) + (bcc if bcc else []) # Attachments for filename in attachments: step("Attaching {}...".format(filename)) part = MIMEBase('application', "octet-stream") part.set_payload(open(filename, "rb").read()) encode_base64(part) import os part.add_header( 'Content-Disposition', 'attachment; filename="{}"'.format( os.path.basename(filename.replace('"', '')))) msg.attach(part) # Content formatting style='' for stylesheet in stylesheets or []: with open(stylesheet) as stylefile: style+=stylefile.read() if md: step("Formating markdown input...") import markdown text = md # TODO: Format plain text html = htmltemplate.format( style = style, body = markdown.markdown(md, output_format='html') ) if ansi: step("Formating ansi input...") import deansi text = ansi # TODO: Clean ansi sequences html = htmltemplate.format( style = deansi.styleSheet()+style, body = "<div class='ansi_terminal'>"+deansi.deansi(ansi)+"</div>", ) content = MIMEMultipart('alternative') if text: content.attach(MIMEText(text,'plain','utf8')) if html: step("Adapting html to mail clients...") import premailer html = premailer.transform(html) content.attach(MIMEText(html,'html','utf8')) import sys #sys.stdout.write(html) msg.attach(content) if dump: with open(dump,'w') as dumpfile: dumpfile.write(msg.as_string()) success("Email dumped as {}".format(dump)) return return # Sending step("Connecting to {host}:{port} as {user}...".format(**smtp)) server = smtplib.SMTP(smtp['host'], smtp['port']) server.starttls() server.login(smtp['user'], smtp['password']) step("\tSending...") server.sendmail(sender, recipients, msg.as_string()) success("\tMail sent") server.quit()
def sendMail(sender, to, subject, text=None, html=None, md=None, ansi=None, cc=[], bcc=[], replyto=[], attachments=[], template=None, config=None, stylesheets=[], dump=None, verbose=True): from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email.mime.text import MIMEText from email.encoders import encode_base64 from email.utils import formataddr, parseaddr def formatAddress(address): return formataddr(parseaddr(address)) def formatAddresses(addresses): return ', '.join(formatAddress(a) for a in addresses) # Headers msg = MIMEMultipart() msg['Subject'] = subject msg['From'] = formatAddress(sender) msg['To'] = formatAddresses(to) if cc: msg['CC'] = formatAddresses(cc) if bcc: msg['BCC'] = formatAddresses(bcc) if replyto: msg['Reply-To'] = formatAddresses(replyto) recipients = to + (cc if cc else []) + (bcc if bcc else []) # Attachments for filename in attachments: step("Attaching {}...".format(filename)) part = MIMEBase('application', "octet-stream") part.set_payload(open(filename, "rb").read()) encode_base64(part) import os part.add_header( 'Content-Disposition', 'attachment; filename="{}"'.format( os.path.basename(filename.replace('"', '')))) msg.attach(part) # Content formatting style = '' for stylesheet in stylesheets or []: with open(stylesheet) as stylefile: style += stylefile.read() if md: step("Formating markdown input...") import markdown text = md # TODO: Format plain text html = htmltemplate.format(style=style, body=markdown.markdown( md, output_format='html')) if ansi: step("Formating ansi input...") import deansi text = ansi # TODO: Clean ansi sequences html = htmltemplate.format( style=deansi.styleSheet() + style, body="<div class='ansi_terminal'>" + deansi.deansi(ansi) + "</div>", ) content = MIMEMultipart('alternative') if text: content.attach(MIMEText(text, 'plain', 'utf8')) if html: step("Adapting html to mail clients...") import premailer html = premailer.transform(html) content.attach(MIMEText(html, 'html', 'utf8')) import sys #sys.stdout.write(html) msg.attach(content) if dump: with open(dump, 'w') as dumpfile: dumpfile.write(msg.as_string()) success("Email dumped as {}".format(dump)) return # Sending sendOverSmtp(config, sender, recipients, msg)