mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
128 lines
4.4 KiB
Python
128 lines
4.4 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
# Copyright (c) 2024, kurokobo <kurokobo@protonmail.com>
|
||
|
# Copyright (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||
|
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
|
||
|
from __future__ import absolute_import, division, print_function
|
||
|
|
||
|
__metaclass__ = type
|
||
|
|
||
|
DOCUMENTATION = r"""
|
||
|
name: timestamp
|
||
|
type: stdout
|
||
|
short_description: Adds simple timestamp for each header
|
||
|
version_added: 9.0.0
|
||
|
description:
|
||
|
- This callback adds simple timestamp for each header.
|
||
|
author: kurokobo (@kurokobo)
|
||
|
options:
|
||
|
timezone:
|
||
|
description:
|
||
|
- Timezone to use for the timestamp in IANA time zone format.
|
||
|
- For example C(America/New_York), C(Asia/Tokyo)). Ignored on Python < 3.9.
|
||
|
ini:
|
||
|
- section: callback_timestamp
|
||
|
key: timezone
|
||
|
env:
|
||
|
- name: ANSIBLE_CALLBACK_TIMESTAMP_TIMEZONE
|
||
|
type: string
|
||
|
format_string:
|
||
|
description:
|
||
|
- Format of the timestamp shown to user in 1989 C standard format.
|
||
|
- >
|
||
|
Refer to L(the Python documentation,https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes)
|
||
|
for the available format codes.
|
||
|
ini:
|
||
|
- section: callback_timestamp
|
||
|
key: format_string
|
||
|
env:
|
||
|
- name: ANSIBLE_CALLBACK_TIMESTAMP_FORMAT_STRING
|
||
|
default: "%H:%M:%S"
|
||
|
type: string
|
||
|
seealso:
|
||
|
- plugin: ansible.posix.profile_tasks
|
||
|
plugin_type: callback
|
||
|
description: >
|
||
|
You can use P(ansible.posix.profile_tasks#callback) callback plugin to time individual tasks and overall execution time
|
||
|
with detailed timestamps.
|
||
|
extends_documentation_fragment:
|
||
|
- ansible.builtin.default_callback
|
||
|
- ansible.builtin.result_format_callback
|
||
|
"""
|
||
|
|
||
|
|
||
|
from ansible.plugins.callback.default import CallbackModule as Default
|
||
|
from ansible.utils.display import get_text_width
|
||
|
from ansible.module_utils.common.text.converters import to_text
|
||
|
from datetime import datetime
|
||
|
import types
|
||
|
import sys
|
||
|
|
||
|
# Store whether the zoneinfo module is available
|
||
|
_ZONEINFO_AVAILABLE = sys.version_info >= (3, 9)
|
||
|
|
||
|
|
||
|
def get_datetime_now(tz):
|
||
|
"""
|
||
|
Returns the current timestamp with the specified timezone
|
||
|
"""
|
||
|
return datetime.now(tz=tz)
|
||
|
|
||
|
|
||
|
def banner(self, msg, color=None, cows=True):
|
||
|
"""
|
||
|
Prints a header-looking line with cowsay or stars with length depending on terminal width (3 minimum) with trailing timestamp
|
||
|
|
||
|
Based on the banner method of Display class from ansible.utils.display
|
||
|
|
||
|
https://github.com/ansible/ansible/blob/4403519afe89138042108e237aef317fd5f09c33/lib/ansible/utils/display.py#L511
|
||
|
"""
|
||
|
timestamp = get_datetime_now(self.timestamp_tzinfo).strftime(self.timestamp_format_string)
|
||
|
timestamp_len = get_text_width(timestamp) + 1 # +1 for leading space
|
||
|
|
||
|
msg = to_text(msg)
|
||
|
if self.b_cowsay and cows:
|
||
|
try:
|
||
|
self.banner_cowsay("%s @ %s" % (msg, timestamp))
|
||
|
return
|
||
|
except OSError:
|
||
|
self.warning("somebody cleverly deleted cowsay or something during the PB run. heh.")
|
||
|
|
||
|
msg = msg.strip()
|
||
|
try:
|
||
|
star_len = self.columns - get_text_width(msg) - timestamp_len
|
||
|
except EnvironmentError:
|
||
|
star_len = self.columns - len(msg) - timestamp_len
|
||
|
if star_len <= 3:
|
||
|
star_len = 3
|
||
|
stars = "*" * star_len
|
||
|
self.display("\n%s %s %s" % (msg, stars, timestamp), color=color)
|
||
|
|
||
|
|
||
|
class CallbackModule(Default):
|
||
|
CALLBACK_VERSION = 2.0
|
||
|
CALLBACK_TYPE = "stdout"
|
||
|
CALLBACK_NAME = "community.general.timestamp"
|
||
|
|
||
|
def __init__(self):
|
||
|
super(CallbackModule, self).__init__()
|
||
|
|
||
|
# Replace the banner method of the display object with the custom one
|
||
|
self._display.banner = types.MethodType(banner, self._display)
|
||
|
|
||
|
def set_options(self, task_keys=None, var_options=None, direct=None):
|
||
|
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
|
||
|
|
||
|
# Store zoneinfo for specified timezone if available
|
||
|
tzinfo = None
|
||
|
if _ZONEINFO_AVAILABLE and self.get_option("timezone"):
|
||
|
from zoneinfo import ZoneInfo
|
||
|
|
||
|
tzinfo = ZoneInfo(self.get_option("timezone"))
|
||
|
|
||
|
# Inject options into the display object
|
||
|
setattr(self._display, "timestamp_tzinfo", tzinfo)
|
||
|
setattr(self._display, "timestamp_format_string", self.get_option("format_string"))
|