diff --git a/changelogs/fragments/log_id.yml b/changelogs/fragments/log_id.yml new file mode 100644 index 00000000000..3233bf796c4 --- /dev/null +++ b/changelogs/fragments/log_id.yml @@ -0,0 +1,2 @@ +minor_changes: + - added configuration item ``TARGET_LOG_INFO`` that allows the user/author to add an information string to the log output on targets. diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml index a6130b58bba..58fa708f82c 100644 --- a/lib/ansible/config/base.yml +++ b/lib/ansible/config/base.yml @@ -1969,6 +1969,15 @@ TAGS_SKIP: ini: - {key: skip, section: tags} version_added: "2.5" +TARGET_LOG_INFO: + name: Target log info + description: A string to insert into target logging for tracking purposes + env: [{name: ANSIBLE_TARGET_LOG_INFO}] + ini: + - {key: target_log_info, section: defaults} + vars: + - name: ansible_target_log_info + version_added: "2.17" TASK_TIMEOUT: name: Task Timeout default: 0 diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index eca66085f3e..8377246ece5 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -1300,10 +1300,16 @@ class AnsibleModule(object): # We want journal to always take text type # syslog takes bytes on py2, text type on py3 if isinstance(msg, binary_type): - journal_msg = remove_values(msg.decode('utf-8', 'replace'), self.no_log_values) + journal_msg = msg.decode('utf-8', 'replace') else: # TODO: surrogateescape is a danger here on Py3 - journal_msg = remove_values(msg, self.no_log_values) + journal_msg = msg + + if self._target_log_info: + journal_msg = ' '.join([self._target_log_info, journal_msg]) + + # ensure we clean up secrets! + journal_msg = remove_values(journal_msg, self.no_log_values) if PY3: syslog_msg = journal_msg diff --git a/lib/ansible/module_utils/common/parameters.py b/lib/ansible/module_utils/common/parameters.py index fb61bd38c49..9e74f59f26d 100644 --- a/lib/ansible/module_utils/common/parameters.py +++ b/lib/ansible/module_utils/common/parameters.py @@ -82,6 +82,7 @@ _ADDITIONAL_CHECKS = ( # if adding boolean attribute, also add to PASS_BOOL # some of this dupes defaults from controller config +# keep in sync with copy in lib/ansible/module_utils/csharp/Ansible.Basic.cs PASS_VARS = { 'check_mode': ('check_mode', False), 'debug': ('_debug', False), @@ -91,6 +92,7 @@ PASS_VARS = { 'module_name': ('_name', None), 'no_log': ('no_log', False), 'remote_tmp': ('_remote_tmp', None), + 'target_log_info': ('_target_log_info', None), 'selinux_special_fs': ('_selinux_special_fs', ['fuse', 'nfs', 'vboxsf', 'ramfs', '9p', 'vfat']), 'shell_executable': ('_shell', '/bin/sh'), 'socket': ('_socket_path', None), diff --git a/lib/ansible/module_utils/csharp/Ansible.Basic.cs b/lib/ansible/module_utils/csharp/Ansible.Basic.cs index 120536331bc..a042af8cecc 100644 --- a/lib/ansible/module_utils/csharp/Ansible.Basic.cs +++ b/lib/ansible/module_utils/csharp/Ansible.Basic.cs @@ -61,6 +61,7 @@ namespace Ansible.Basic private Dictionary passVars = new Dictionary() { // null values means no mapping, not used in Ansible.Basic.AnsibleModule + // keep in sync with python counterpart in lib/ansible/module_utils/common/parameters.py { "check_mode", "CheckMode" }, { "debug", "DebugMode" }, { "diff", "DiffMode" }, @@ -74,6 +75,7 @@ namespace Ansible.Basic { "socket", null }, { "string_conversion_action", null }, { "syslog_facility", null }, + { "target_log_info", "TargetLogInfo"}, { "tmpdir", "tmpdir" }, { "verbosity", "Verbosity" }, { "version", "AnsibleVersion" }, @@ -127,6 +129,7 @@ namespace Ansible.Basic public bool KeepRemoteFiles { get; private set; } public string ModuleName { get; private set; } public bool NoLog { get; private set; } + public string TargetLogInfo { get; private set; } public int Verbosity { get; private set; } public string AnsibleVersion { get; private set; } @@ -259,6 +262,7 @@ namespace Ansible.Basic DiffMode = false; KeepRemoteFiles = false; ModuleName = "undefined win module"; + TargetLogInfo = ""; NoLog = (bool)argumentSpec["no_log"]; Verbosity = 0; AppDomain.CurrentDomain.ProcessExit += CleanupFiles; @@ -374,9 +378,20 @@ namespace Ansible.Basic logSource = "Application"; } } + + if (String.IsNullOrWhiteSpace(TargetLogInfo)) + { + message = String.Format("{0} - {1}", ModuleName, message); + } + else + { + message = String.Format("{0} {1} - {2}", ModuleName, TargetLogInfo, message); + } + if (sanitise) + { message = (string)RemoveNoLogValues(message, noLogValues); - message = String.Format("{0} - {1}", ModuleName, message); + } using (EventLog eventLog = new EventLog("Application")) { diff --git a/lib/ansible/plugins/action/__init__.py b/lib/ansible/plugins/action/__init__.py index b557e3b68cc..7894c7f993c 100644 --- a/lib/ansible/plugins/action/__init__.py +++ b/lib/ansible/plugins/action/__init__.py @@ -1000,6 +1000,9 @@ class ActionBase(ABC): # tells the module to ignore options that are not in its argspec. module_args['_ansible_ignore_unknown_opts'] = ignore_unknown_opts + # allow user to insert string to add context to remote loggging + module_args['_ansible_target_log_info'] = C.config.get_config_value('TARGET_LOG_INFO', variables=task_vars) + def _execute_module(self, module_name=None, module_args=None, tmp=None, task_vars=None, persist_files=False, delete_remote_tmp=None, wrap_async=False, ignore_unknown_opts: bool = False): ''' diff --git a/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1 b/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1 index df8bf8db794..625cb210874 100644 --- a/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1 +++ b/test/integration/targets/module_utils_Ansible.Basic/library/ansible_basic_tests.ps1 @@ -155,6 +155,7 @@ $tests = @{ "_ansible_shell_executable": "ignored", "_ansible_socket": "ignored", "_ansible_syslog_facility": "ignored", + "_ansible_target_log_info": "ignored", "_ansible_tmpdir": "$($m_tmpdir -replace "\\", "\\")", "_ansible_verbosity": 3, "_ansible_version": "2.8.0"