summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cloudinit/reporting/events.py58
-rw-r--r--tests/unittests/test_reporting.py15
2 files changed, 56 insertions, 17 deletions
diff --git a/cloudinit/reporting/events.py b/cloudinit/reporting/events.py
index e35e41dd..2f767f64 100644
--- a/cloudinit/reporting/events.py
+++ b/cloudinit/reporting/events.py
@@ -2,17 +2,22 @@
# This file is part of cloud-init. See LICENCE file for license information.
#
"""
-cloud-init events
+events for reporting.
-Report events in a structured manner.
-The events here are most likely used via reporting.
+The events here are designed to be used with reporting.
+They can be published to registered handlers with report_event.
"""
+import base64
+import os.path
+import time
from . import instantiated_handler_registry
FINISH_EVENT_TYPE = 'finish'
START_EVENT_TYPE = 'start'
+DEFAULT_EVENT_ORIGIN = 'cloudinit'
+
class _nameset(set):
def __getattr__(self, name):
@@ -27,10 +32,13 @@ status = _nameset(("SUCCESS", "WARN", "FAIL"))
class ReportingEvent(object):
"""Encapsulation of event formatting."""
- def __init__(self, event_type, name, description):
+ def __init__(self, event_type, name, description,
+ origin=DEFAULT_EVENT_ORIGIN, timestamp=time.time()):
self.event_type = event_type
self.name = name
self.description = description
+ self.origin = origin
+ self.timestamp = timestamp
def as_string(self):
"""The event represented as a string."""
@@ -40,15 +48,20 @@ class ReportingEvent(object):
def as_dict(self):
"""The event represented as a dictionary."""
return {'name': self.name, 'description': self.description,
- 'event_type': self.event_type}
+ 'event_type': self.event_type, 'origin': self.origin,
+ 'timestamp': self.timestamp}
class FinishReportingEvent(ReportingEvent):
- def __init__(self, name, description, result=status.SUCCESS):
+ def __init__(self, name, description, result=status.SUCCESS,
+ post_files=None):
super(FinishReportingEvent, self).__init__(
FINISH_EVENT_TYPE, name, description)
self.result = result
+ if post_files is None:
+ post_files = []
+ self.post_files = post_files
if result not in status:
raise ValueError("Invalid result: %s" % result)
@@ -60,6 +73,8 @@ class FinishReportingEvent(ReportingEvent):
"""The event represented as json friendly."""
data = super(FinishReportingEvent, self).as_dict()
data['result'] = self.result
+ if self.post_files:
+ data['files'] = _collect_file_info(self.post_files)
return data
@@ -78,12 +93,13 @@ def report_event(event):
def report_finish_event(event_name, event_description,
- result=status.SUCCESS):
+ result=status.SUCCESS, post_files=None):
"""Report a "finish" event.
See :py:func:`.report_event` for parameter details.
"""
- event = FinishReportingEvent(event_name, event_description, result)
+ event = FinishReportingEvent(event_name, event_description, result,
+ post_files=post_files)
return report_event(event)
@@ -133,13 +149,17 @@ class ReportEventStack(object):
value is FAIL.
"""
def __init__(self, name, description, message=None, parent=None,
- reporting_enabled=None, result_on_exception=status.FAIL):
+ reporting_enabled=None, result_on_exception=status.FAIL,
+ post_files=None):
self.parent = parent
self.name = name
self.description = description
self.message = message
self.result_on_exception = result_on_exception
self.result = status.SUCCESS
+ if post_files is None:
+ post_files = []
+ self.post_files = post_files
# use parents reporting value if not provided
if reporting_enabled is None:
@@ -205,6 +225,22 @@ class ReportEventStack(object):
if self.parent:
self.parent.children[self.name] = (result, msg)
if self.reporting_enabled:
- report_finish_event(self.fullname, msg, result)
+ report_finish_event(self.fullname, msg, result,
+ post_files=self.post_files)
+
+
+def _collect_file_info(files):
+ if not files:
+ return None
+ ret = []
+ for fname in files:
+ if not os.path.isfile(fname):
+ content = None
+ else:
+ with open(fname, "rb") as fp:
+ content = base64.b64encode(fp.read()).decode()
+ ret.append({'path': fname, 'content': content,
+ 'encoding': 'base64'})
+ return ret
-# vi: ts=4 expandtab
+# vi: ts=4 expandtab syntax=python
diff --git a/tests/unittests/test_reporting.py b/tests/unittests/test_reporting.py
index bb67ef73..0a441adf 100644
--- a/tests/unittests/test_reporting.py
+++ b/tests/unittests/test_reporting.py
@@ -241,7 +241,8 @@ class TestReportingEventStack(TestCase):
self.assertEqual(
[mock.call('myname', 'mydesc')], report_start.call_args_list)
self.assertEqual(
- [mock.call('myname', 'mydesc', events.status.SUCCESS)],
+ [mock.call('myname', 'mydesc', events.status.SUCCESS,
+ post_files=[])],
report_finish.call_args_list)
@mock.patch('cloudinit.reporting.events.report_finish_event')
@@ -256,7 +257,7 @@ class TestReportingEventStack(TestCase):
pass
self.assertEqual([mock.call(name, desc)], report_start.call_args_list)
self.assertEqual(
- [mock.call(name, desc, events.status.FAIL)],
+ [mock.call(name, desc, events.status.FAIL, post_files=[])],
report_finish.call_args_list)
@mock.patch('cloudinit.reporting.events.report_finish_event')
@@ -272,7 +273,7 @@ class TestReportingEventStack(TestCase):
pass
self.assertEqual([mock.call(name, desc)], report_start.call_args_list)
self.assertEqual(
- [mock.call(name, desc, events.status.WARN)],
+ [mock.call(name, desc, events.status.WARN, post_files=[])],
report_finish.call_args_list)
@mock.patch('cloudinit.reporting.events.report_start_event')
@@ -301,7 +302,7 @@ class TestReportingEventStack(TestCase):
child.result = events.status.WARN
report_finish.assert_called_with(
- "topname", "topdesc", events.status.WARN)
+ "topname", "topdesc", events.status.WARN, post_files=[])
@mock.patch('cloudinit.reporting.events.report_finish_event')
def test_message_used_in_finish(self, report_finish):
@@ -309,7 +310,8 @@ class TestReportingEventStack(TestCase):
message="mymessage"):
pass
self.assertEqual(
- [mock.call("myname", "mymessage", events.status.SUCCESS)],
+ [mock.call("myname", "mymessage", events.status.SUCCESS,
+ post_files=[])],
report_finish.call_args_list)
@mock.patch('cloudinit.reporting.events.report_finish_event')
@@ -317,7 +319,8 @@ class TestReportingEventStack(TestCase):
with events.ReportEventStack("myname", "mydesc") as c:
c.message = "all good"
self.assertEqual(
- [mock.call("myname", "all good", events.status.SUCCESS)],
+ [mock.call("myname", "all good", events.status.SUCCESS,
+ post_files=[])],
report_finish.call_args_list)
@mock.patch('cloudinit.reporting.events.report_start_event')