mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add millisecond data to splunk callback timestamp (#1462)
* Add millisecond data to timestamp * Add flag to control splunk milliseconds * Update changelogs/fragments/1462-splunk-millisecond.yaml Co-authored-by: Amin Vakil <info@aminvakil.com> * Apply suggestions from code review Co-authored-by: Felix Fontein <felix@fontein.de> * Apply more suggestions from review * Whitespace Co-authored-by: Amin Vakil <info@aminvakil.com> Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
8d9fd52d3d
commit
91272d027b
4 changed files with 90 additions and 3 deletions
2
changelogs/fragments/1462-splunk-millisecond.yaml
Normal file
2
changelogs/fragments/1462-splunk-millisecond.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- splunk callback - new parameter ``include_milliseconds`` to add milliseconds to existing timestamp field (https://github.com/ansible-collections/community.general/pull/1462).
|
|
@ -57,6 +57,17 @@ DOCUMENTATION = '''
|
|||
type: bool
|
||||
default: true
|
||||
version_added: '1.0.0'
|
||||
include_milliseconds:
|
||||
description: Whether to include milliseconds as part of the generated timestamp field in the event
|
||||
sent to the Splunk HTTP collector
|
||||
env:
|
||||
- name: SPLUNK_INCLUDE_MILLISECONDS
|
||||
ini:
|
||||
- section: callback_splunk
|
||||
key: include_milliseconds
|
||||
type: bool
|
||||
default: false
|
||||
version_added: 2.0.0
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
|
@ -96,7 +107,7 @@ class SplunkHTTPCollectorSource(object):
|
|||
self.ip_address = socket.gethostbyname(socket.gethostname())
|
||||
self.user = getpass.getuser()
|
||||
|
||||
def send_event(self, url, authtoken, validate_certs, state, result, runtime):
|
||||
def send_event(self, url, authtoken, validate_certs, include_milliseconds, state, result, runtime):
|
||||
if result._task_fields['args'].get('_ansible_check_mode') is True:
|
||||
self.ansible_check_mode = True
|
||||
|
||||
|
@ -116,8 +127,13 @@ class SplunkHTTPCollectorSource(object):
|
|||
data['uuid'] = result._task._uuid
|
||||
data['session'] = self.session
|
||||
data['status'] = state
|
||||
data['timestamp'] = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S '
|
||||
'+0000')
|
||||
|
||||
if include_milliseconds:
|
||||
time_format = '%Y-%m-%d %H:%M:%S.%f +0000'
|
||||
else:
|
||||
time_format = '%Y-%m-%d %H:%M:%S +0000'
|
||||
|
||||
data['timestamp'] = datetime.utcnow().strftime(time_format)
|
||||
data['host'] = self.host
|
||||
data['ip_address'] = self.ip_address
|
||||
data['user'] = self.user
|
||||
|
@ -158,6 +174,7 @@ class CallbackModule(CallbackBase):
|
|||
self.url = None
|
||||
self.authtoken = None
|
||||
self.validate_certs = None
|
||||
self.include_milliseconds = None
|
||||
self.splunk = SplunkHTTPCollectorSource()
|
||||
|
||||
def _runtime(self, result):
|
||||
|
@ -193,6 +210,8 @@ class CallbackModule(CallbackBase):
|
|||
|
||||
self.validate_certs = self.get_option('validate_certs')
|
||||
|
||||
self.include_milliseconds = self.get_option('include_milliseconds')
|
||||
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
self.splunk.ansible_playbook = basename(playbook._file_name)
|
||||
|
||||
|
@ -207,6 +226,7 @@ class CallbackModule(CallbackBase):
|
|||
self.url,
|
||||
self.authtoken,
|
||||
self.validate_certs,
|
||||
self.include_milliseconds,
|
||||
'OK',
|
||||
result,
|
||||
self._runtime(result)
|
||||
|
@ -217,6 +237,7 @@ class CallbackModule(CallbackBase):
|
|||
self.url,
|
||||
self.authtoken,
|
||||
self.validate_certs,
|
||||
self.include_milliseconds,
|
||||
'SKIPPED',
|
||||
result,
|
||||
self._runtime(result)
|
||||
|
@ -227,6 +248,7 @@ class CallbackModule(CallbackBase):
|
|||
self.url,
|
||||
self.authtoken,
|
||||
self.validate_certs,
|
||||
self.include_milliseconds,
|
||||
'FAILED',
|
||||
result,
|
||||
self._runtime(result)
|
||||
|
@ -237,6 +259,7 @@ class CallbackModule(CallbackBase):
|
|||
self.url,
|
||||
self.authtoken,
|
||||
self.validate_certs,
|
||||
self.include_milliseconds,
|
||||
'FAILED',
|
||||
result,
|
||||
self._runtime(result)
|
||||
|
@ -247,6 +270,7 @@ class CallbackModule(CallbackBase):
|
|||
self.url,
|
||||
self.authtoken,
|
||||
self.validate_certs,
|
||||
self.include_milliseconds,
|
||||
'UNREACHABLE',
|
||||
result,
|
||||
self._runtime(result)
|
||||
|
|
0
tests/unit/plugins/callback/__init__.py
Normal file
0
tests/unit/plugins/callback/__init__.py
Normal file
61
tests/unit/plugins/callback/test_splunk.py
Normal file
61
tests/unit/plugins/callback/test_splunk.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible.executor.task_result import TaskResult
|
||||
from ansible_collections.community.general.tests.unit.compat import unittest
|
||||
from ansible_collections.community.general.tests.unit.compat.mock import patch, call, MagicMock, Mock
|
||||
from ansible_collections.community.general.plugins.callback.splunk import SplunkHTTPCollectorSource
|
||||
from datetime import datetime
|
||||
|
||||
import json
|
||||
|
||||
|
||||
class TestSplunkClient(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.splunk = SplunkHTTPCollectorSource()
|
||||
self.mock_task = Mock('MockTask')
|
||||
self.mock_task._role = 'myrole'
|
||||
self.mock_task._uuid = 'myuuid'
|
||||
self.task_fields = {'args': {}}
|
||||
self.mock_host = Mock('MockHost')
|
||||
self.mock_host.name = 'myhost'
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.callback.splunk.datetime')
|
||||
@patch('ansible_collections.community.general.plugins.callback.splunk.open_url')
|
||||
def test_timestamp_with_milliseconds(self, open_url_mock, mock_datetime):
|
||||
mock_datetime.utcnow.return_value = datetime(2020, 12, 1)
|
||||
result = TaskResult(host=self.mock_host, task=self.mock_task, return_data={}, task_fields=self.task_fields)
|
||||
|
||||
self.splunk.send_event(url='endpoint', authtoken='token', validate_certs=False, include_milliseconds=True, state='OK', result=result, runtime=100)
|
||||
|
||||
args, kwargs = open_url_mock.call_args
|
||||
sent_data = json.loads(args[1])
|
||||
|
||||
self.assertEqual(sent_data['event']['timestamp'], '2020-12-01 00:00:00.000000 +0000')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.callback.splunk.datetime')
|
||||
@patch('ansible_collections.community.general.plugins.callback.splunk.open_url')
|
||||
def test_timestamp_without_milliseconds(self, open_url_mock, mock_datetime):
|
||||
mock_datetime.utcnow.return_value = datetime(2020, 12, 1)
|
||||
result = TaskResult(host=self.mock_host, task=self.mock_task, return_data={}, task_fields=self.task_fields)
|
||||
|
||||
self.splunk.send_event(url='endpoint', authtoken='token', validate_certs=False, include_milliseconds=False, state='OK', result=result, runtime=100)
|
||||
|
||||
args, kwargs = open_url_mock.call_args
|
||||
sent_data = json.loads(args[1])
|
||||
|
||||
self.assertEqual(sent_data['event']['timestamp'], '2020-12-01 00:00:00 +0000')
|
Loading…
Reference in a new issue