Repository: kangasta/pullnrun

Issue:
Add logging to remote target

Discussion:

Patch:
diff --git a/pullnrun/_log.py b/pullnrun/_log.py
index 10ce05b..dd06f9a 100644
--- a/pullnrun/_log.py
+++ b/pullnrun/_log.py
@@ -1,7 +1,9 @@
 from os import getenv
 from uuid import uuid4
 
-from pullnrun._utils import get_log_entry, timestamp
+from requests import request
+
+from pullnrun._utils import as_list, get_log_entry, timestamp
 
 def _status(output_dict):
     status = output_dict.get('status')
@@ -100,16 +102,31 @@ def log_to_console(output_dict):
         end = '\n' if output[-1] != '\n' else ''
         print(f'\n{output}{end}')
 
+def log_to_url(url, id_, log_entry, method=None):
+    data = {
+        'id': id_,
+        'entry': log_entry,
+    }
+    request(method or 'POST', url, json=data)
+    # TODO: communicate errors
+
 class Log:
-    def __init__(self, quiet=False):
+    def __init__(self, quiet=False, targets=None):
         self._start = None
         self._end = None
         self._id = getenv('PULLNRUN_ID', str(uuid4()))
         self._to_console = not quiet
+        self._targets = as_list(targets)
 
-    def __call__(self, log_entry):
+    def _log(self, log_entry):
         if self._to_console:
             log_to_console(log_entry)
+        for target in self._targets:
+            if target.get('to') == 'url':
+                log_to_url(target.get('url'), self._id, log_entry, target.get('method'))
+
+    def __call__(self, log_entry):
+        self._log(log_entry)
 
     @property
     def id(self):
@@ -117,11 +134,13 @@ class Log:
 
     def start(self):
         self._start = timestamp()
-        if self._to_console:
-            log_to_console(get_log_entry('main', 'STARTED', start=self._start, id=self._id))
+        self._log(
+            get_log_entry('main', 'STARTED', start=self._start, id=self._id)
+        )
 
     def end(self, success, fail):
         self._end = timestamp()
         status = 'SUCCESS' if success > 0 and fail == 0 else 'ERROR'
-        if self._to_console:
-            log_to_console(get_log_entry('main', status, start=self._start, end=self._end, success=success, fail=fail))
+        self._log(
+            get_log_entry('main', status, start=self._start, end=self._end, success=success, fail=fail)
+        )
diff --git a/pullnrun/_main.py b/pullnrun/_main.py
index d7cea31..da00464 100644
--- a/pullnrun/_main.py
+++ b/pullnrun/_main.py
@@ -27,7 +27,8 @@ def _validate(input_dict):
 def main(input_dict, quiet=False):
     _validate(input_dict)
 
-    log = Log(quiet)
+    log_targets = input_dict.get('log')
+    log = Log(quiet, log_targets)
     log.start()
 
     success, error = (0, 0, )
diff --git a/pullnrun/schema.json b/pullnrun/schema.json
index 6b88b71..17961af 100644
--- a/pullnrun/schema.json
+++ b/pullnrun/schema.json
@@ -84,6 +84,20 @@
 				"directory": { "type": "string" }
 			},
 			"required": [ "command" ]
+		},
+		"log_http": {
+			"type": "object",
+			"properties": {
+				"to": { "const": "url" },
+				"url": { "type": "string" },
+				"method": {"type": "string" }
+			},
+			"required": [ "to", "url" ]
+		},
+		"log": {
+			"oneOf": [
+				{ "$ref": "#/definitions/log_http" }
+			]
 		}
 	},
 	"type": "object",
@@ -114,6 +128,15 @@
 				},
 				{ "$ref" :"#/definitions/run" }
 			]
+		},
+		"log": {
+			"oneOf": [
+				{
+					"type": "array",
+					"items": { "$ref" :"#/definitions/log" }
+				},
+				{ "$ref" :"#/definitions/log" }
+			]
 		}
 	}
 }
\ No newline at end of file


Test patch:
diff --git a/tst/test_log.py b/tst/test_log.py
index 5db69da..95025cf 100644
--- a/tst/test_log.py
+++ b/tst/test_log.py
@@ -90,3 +90,25 @@ class LogTest(TestCase):
             output = print_mock.call_args[-2][0]
 
             self.assertIn(result, output)
+
+    @patch('builtins.print')
+    @patch('pullnrun._log.request')
+    def test_log_sends_entries_via_http(self, request_mock, print_mock):
+        log = Log(quiet=True, targets={'to': 'url', 'url': 'test_url', 'method': 'PUT'})
+
+        entry = {'type': 'run', 'status': 'STARTED'}
+        log(entry)
+
+        request_mock.assert_called_with('PUT', 'test_url', json={'id': log.id, 'entry': entry})
+        print_mock.assert_not_called()
+
+    @patch('builtins.print')
+    @patch('pullnrun._log.request')
+    def test_log_sends_entries_as_post_by_default(self, request_mock, print_mock):
+        log = Log(quiet=True, targets={'to': 'url', 'url': 'test_url'})
+
+        entry = {'type': 'run', 'status': 'STARTED'}
+        log(entry)
+
+        request_mock.assert_called_with('POST', 'test_url', json={'id': log.id, 'entry': entry})
+        print_mock.assert_not_called()