Skip to content

Commit

Permalink
teuthology-suite: add Rocket.Chat notification
Browse files Browse the repository at this point in the history
Add Rocket.Chat notification for sleep before teardown.
For details see https://rocket.chat/

Signed-off-by: Kyr Shatskyy <[email protected]>
  • Loading branch information
Kyr Shatskyy committed Dec 8, 2020
1 parent e0aaa9b commit 7afe83c
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 0 deletions.
3 changes: 3 additions & 0 deletions scripts/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
When tests finish or time out, send an email
here. May also be specified in ~/.teuthology.yaml
as 'results_email'
--rocketchat <rocketchat> Comma separated list of Rocket.Chat channels where
to send a message when tests finished or time out.
To be used with --sleep-before-teardown option.
-N <num>, --num <num> Number of times to run/queue the job
[default: 1]
-l <jobs>, --limit <jobs> Queue at most this many jobs
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
'configparser',
'ansible>=2.0',
'prettytable',
'rocket-python >= 1.2.15',
'manhole',
'humanfriendly',
],
Expand Down
1 change: 1 addition & 0 deletions teuthology/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ class TeuthologyConfig(YamlConfig):
'size': 1,
},
},
'rocketchat': None,
'sleep_before_teardown': 0,
}

Expand Down
86 changes: 86 additions & 0 deletions teuthology/run_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
import time
import types
import yaml

from copy import deepcopy
from humanfriendly import format_timespan
Expand Down Expand Up @@ -203,6 +204,41 @@ def run_tasks(tasks, ctx):
del exc_info
timer.mark("tasks complete")


def build_rocketchat_message(ctx, stack, sleep_time_sec, template_path=None):
message_template_path = template_path or os.path.dirname(__file__) + \
'/templates/rocketchat-sleep-before-teardown.jinja2'

with open(message_template_path) as f:
template_text = f.read()

template = jinja2.Template(template_text)
archive_path = ctx.config.get('archive_path')
job_id = ctx.config.get('job_id')
status = get_status(ctx.summary)
stack_path = ' -> '.join(task for task, _ in stack)
suite_name=ctx.config.get('suite')
sleep_date=time.time()
sleep_date_str=time.strftime('%Y-%m-%d %H:%M:%S',
time.gmtime(sleep_date))

message = template.render(
sleep_time=format_timespan(sleep_time_sec),
sleep_time_sec=sleep_time_sec,
sleep_date=sleep_date_str,
owner=ctx.owner,
run_name=ctx.name,
job_id=ctx.config.get('job_id'),
job_desc=ctx.config.get('description'),
job_info=get_results_url(ctx.name, job_id),
job_logs=get_http_log_path(archive_path, job_id),
suite_name=suite_name,
status=status,
task_stack=stack_path,
)
return message


def build_email_body(ctx, stack, sleep_time_sec):
email_template_path = os.path.dirname(__file__) + \
'/templates/email-sleep-before-teardown.jinja2'
Expand Down Expand Up @@ -239,7 +275,57 @@ def build_email_body(ctx, stack, sleep_time_sec):
)
return (subject.strip(), body.strip())


def rocketchat_send_message(ctx, message, channels):
"""
Send the message to the given RocketChat channels
Before sending the message we read the config file
from `~/.config/rocketchat.api/settings.yaml` which
must include next records:
username: 'userloginname'
password: 'userbigsecret'
domain: 'https://chat.suse.de'
:param message: plain text message content in the Rocket.Chat
messaging format
:param channels: a list of channels where to send the message,
the user private channel should be prefixed
with '@' symbol
"""
try:
from rocketchat.api import RocketChatAPI
except Exception as e:
log.warning(f'rocketchat: Failed to import rocketchat.api: {e}')
return

settings_path = \
os.environ.get('HOME') + '/.config/rocketchat.api/settings.yaml'

try:
with open(settings_path) as f:
settings = yaml.safe_load(f)
except Exception as e:
log.warning(f'rocketchat: Failed to load settings from {settings_path}: {e}')

r = RocketChatAPI(settings=settings)
for channel in channels:
try:
r.send_message(message, channel)
except Exception as e:
log.warning(f'rocketchat: Failed to send message to "{channel}" channel: {e}')


def notify_sleep_before_teardown(ctx, stack, sleep_time):
rocketchat = ctx.config.get('rocketchat', None)

if rocketchat:
channels = [_ for _ in [_.strip() for _ in rocketchat.split(',')] if _]
log.info("Sending a message to Rocket.Chat channels: %s", channels)
message = build_rocketchat_message(ctx, stack, sleep_time)
rocketchat_send_message(ctx, message, channels)

email = ctx.config.get('email', None)
if not email:
# we have no email configured, return silently
Expand Down
2 changes: 2 additions & 0 deletions teuthology/suite/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ def build_base_config(self):
job_config.owner = self.args.owner
if self.args.sleep_before_teardown:
job_config.sleep_before_teardown = int(self.args.sleep_before_teardown)
if self.args.rocketchat:
job_config.rocketchat = self.args.rocketchat
return job_config

def build_base_args(self):
Expand Down
6 changes: 6 additions & 0 deletions teuthology/templates/rocketchat-sleep-before-teardown.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The teuthology job [{{ job_id }}]({{ job_info }}) for suite *{{ suite_name }}* owned by '{{ owner }}' has fallen asleep with status '{{ status }}' at {{ sleep_date }} for __{{ sleep_time }}__ ({{ sleep_time_sec }} seconds).
Open [teuthology.log]({{ job_logs }}teuthology.log) for details, or go to [all logs]({{ job_logs}}).

Job Description: {{ job_desc }}
Run Name: {{ run_name }}
Task Stack: {{ task_stack }}

0 comments on commit 7afe83c

Please sign in to comment.