Compare commits
No commits in common. "c8s" and "c8-beta" have entirely different histories.
8
.ansible-core.metadata
Normal file
8
.ansible-core.metadata
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
560f248ccb0b98256c5b50c86a002c2c1e57edb6 SOURCES/Jinja2-3.1.2.tar.gz
|
||||||
|
192b9f6598e1ae036301f72781973c6f46e50aa2 SOURCES/MarkupSafe-2.1.2.tar.gz
|
||||||
|
4ae417bcadf07c709e0819f489e08248d9a3971b SOURCES/ansible-core-2.16.3.tar.gz
|
||||||
|
7cb698b495d479255d56642ccd8d402dcbd7fe97 SOURCES/ansible-documentation-2.16.3.tar.gz
|
||||||
|
6e53dd117d09e6cd5d8596bf99a0dcbb202b8aad SOURCES/docutils-0.20.1.tar.gz
|
||||||
|
b8caff3bec760723db6af4092c68075e22bdb769 SOURCES/packaging-21.3.tar.gz
|
||||||
|
96464a9452e95e980c3a1fad1020fe00e29c0ae3 SOURCES/pyparsing-3.0.7.tar.gz
|
||||||
|
2f587f4095bb70039c1d995635ae55af8eab08dc SOURCES/resolvelib-1.0.1.tar.gz
|
||||||
34
.gitignore
vendored
34
.gitignore
vendored
@ -1,28 +1,8 @@
|
|||||||
SOURCES/Jinja2-3.1.2.tar.gz
|
SOURCES/Jinja2-3.1.2.tar.gz
|
||||||
SOURCES/MarkupSafe-2.1.0.tar.gz
|
SOURCES/MarkupSafe-2.1.2.tar.gz
|
||||||
SOURCES/ansible-core-2.14.2.tar.gz
|
SOURCES/ansible-core-2.16.3.tar.gz
|
||||||
SOURCES/packaging-20.4.tar.gz
|
SOURCES/ansible-documentation-2.16.3.tar.gz
|
||||||
SOURCES/pyparsing-2.4.7.tar.gz
|
SOURCES/docutils-0.20.1.tar.gz
|
||||||
SOURCES/resolvelib-0.5.4.tar.gz
|
SOURCES/packaging-21.3.tar.gz
|
||||||
/Jinja2-3.1.2.tar.gz
|
SOURCES/pyparsing-3.0.7.tar.gz
|
||||||
/MarkupSafe-2.1.0.tar.gz
|
SOURCES/resolvelib-1.0.1.tar.gz
|
||||||
/ansible-core-2.14.2.tar.gz
|
|
||||||
/packaging-20.4.tar.gz
|
|
||||||
/pyparsing-2.4.7.tar.gz
|
|
||||||
/resolvelib-0.5.4.tar.gz
|
|
||||||
/MarkupSafe-2.1.2.tar.gz
|
|
||||||
/ansible-core-2.15.0.tar.gz
|
|
||||||
/packaging-21.3.tar.gz
|
|
||||||
/pyparsing-3.0.7.tar.gz
|
|
||||||
/resolvelib-1.0.1.tar.gz
|
|
||||||
/ansible-core-2.15.1.tar.gz
|
|
||||||
/ansible-core-2.15.2.tar.gz
|
|
||||||
/ansible-core-2.15.3.tar.gz
|
|
||||||
/ansible-documentation-2.15.3.tar.gz
|
|
||||||
/docutils-0.20.1.tar.gz
|
|
||||||
/ansible-core-2.16.1.tar.gz
|
|
||||||
/ansible-documentation-2.16.1.tar.gz
|
|
||||||
/ansible-core-2.16.2.tar.gz
|
|
||||||
/ansible-documentation-2.16.2.tar.gz
|
|
||||||
/ansible-core-2.16.3.tar.gz
|
|
||||||
/ansible-documentation-2.16.3.tar.gz
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
Name: ansible-core
|
Name: ansible-core
|
||||||
Summary: SSH-based configuration management, deployment, and task execution system
|
Summary: SSH-based configuration management, deployment, and task execution system
|
||||||
Version: 2.16.3
|
Version: 2.16.3
|
||||||
Release: 3%{?dist}
|
Release: 2%{?dist}
|
||||||
ExcludeArch: i686
|
ExcludeArch: i686
|
||||||
|
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
@ -59,11 +59,6 @@ Source8: https://sourceforge.net/projects/docutils/files/docutils/%{docutils_ver
|
|||||||
|
|
||||||
Patch0: remove-bundled-deps-from-requirements.patch
|
Patch0: remove-bundled-deps-from-requirements.patch
|
||||||
|
|
||||||
%if 0%{!?centos:1} && 0%{?rhel}
|
|
||||||
Source99: telemetry.py
|
|
||||||
Patch99: telemetry.patch
|
|
||||||
%endif
|
|
||||||
|
|
||||||
URL: http://ansible.com
|
URL: http://ansible.com
|
||||||
|
|
||||||
# We conflict old ansible, and any version of ansible-base.
|
# We conflict old ansible, and any version of ansible-base.
|
||||||
@ -128,10 +123,6 @@ developed for ansible.
|
|||||||
# Fix all Python shebangs recursively in ansible-test
|
# Fix all Python shebangs recursively in ansible-test
|
||||||
%{py3_shebang_fix} test/lib/ansible_test
|
%{py3_shebang_fix} test/lib/ansible_test
|
||||||
|
|
||||||
%if 0%{!?centos:1} && 0%{?rhel}
|
|
||||||
%patch -P99 -p1
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%{py3_build}
|
%{py3_build}
|
||||||
|
|
||||||
@ -186,12 +177,6 @@ mkdir -p %{buildroot}%{_sysconfdir}/ansible/roles/
|
|||||||
cp ../ansible-documentation-%{version}/examples/hosts %{buildroot}%{_sysconfdir}/ansible/
|
cp ../ansible-documentation-%{version}/examples/hosts %{buildroot}%{_sysconfdir}/ansible/
|
||||||
cp ../ansible-documentation-%{version}/examples/ansible.cfg %{buildroot}%{_sysconfdir}/ansible/
|
cp ../ansible-documentation-%{version}/examples/ansible.cfg %{buildroot}%{_sysconfdir}/ansible/
|
||||||
|
|
||||||
%if 0%{!?centos:1} && 0%{?rhel}
|
|
||||||
mkdir -p %{buildroot}%{_datadir}/ansible/telemetry
|
|
||||||
cp %{SOURCE99} %{buildroot}%{_datadir}/ansible/telemetry/
|
|
||||||
%py_byte_compile %{__python3} %{buildroot}%{_datadir}/ansible/telemetry/telemetry.py
|
|
||||||
%endif
|
|
||||||
|
|
||||||
mkdir -p %{buildroot}/%{_mandir}/man1/
|
mkdir -p %{buildroot}/%{_mandir}/man1/
|
||||||
|
|
||||||
mkdir -p docs/man/man1
|
mkdir -p docs/man/man1
|
||||||
@ -225,9 +210,6 @@ strip --strip-unneeded %{vendor_path}/markupsafe/_speedups%{python3_ext_suffix}
|
|||||||
%{python3_sitelib}/ansible_test
|
%{python3_sitelib}/ansible_test
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Wed Jul 29 2026 Dimitri Savineau <dsavinea@redhat.com> - 2.16.3-3
|
|
||||||
- Add telemetry for RHEL (RHEL-219532)
|
|
||||||
|
|
||||||
* Mon Feb 05 2024 Dimitri Savineau <dsavinea@redhat.com> - 2.16.3-2
|
* Mon Feb 05 2024 Dimitri Savineau <dsavinea@redhat.com> - 2.16.3-2
|
||||||
- rebuild with python 3.12 (RHEL-24141)
|
- rebuild with python 3.12 (RHEL-24141)
|
||||||
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
--- !Policy
|
|
||||||
product_versions:
|
|
||||||
- rhel-8
|
|
||||||
decision_context: osci_compose_gate
|
|
||||||
rules:
|
|
||||||
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}
|
|
||||||
8
sources
8
sources
@ -1,8 +0,0 @@
|
|||||||
SHA512 (ansible-core-2.16.3.tar.gz) = 62b7d23d3d639f118a4b87dccc02ec5f373fd56ae6c5fb56c8adf0818d0f5bbf3b6de47a29da9ef2d8c3f4b7e3a99978677bc9bfda1eb4cb9640b79abb763f77
|
|
||||||
SHA512 (ansible-documentation-2.16.3.tar.gz) = c073b0b961e38bee560be78e2c12534facec891f6e375df14fdcaf99241f711cf6955ee58b936f7f23ab62a732d2dbde5fd279976989be06e747c2bf3db41661
|
|
||||||
SHA512 (docutils-0.20.1.tar.gz) = a0ddca315d03677003036d6a8052ac96fbd3fcc4508564938ea684d79bedb4d322d83449c7b26e55b19b0aadd6e46ca9ac409bb16279a20f06c70e9c15ef5eb0
|
|
||||||
SHA512 (Jinja2-3.1.2.tar.gz) = 5dfe122c1beef5305b34d25f22f96607bd3a6cba098b03091850ea36fefe62b645a7218d7584b35bea252393ac922c9bb3654a9e90f23bcfb273e811fcf2f2c1
|
|
||||||
SHA512 (MarkupSafe-2.1.2.tar.gz) = 84dbeddaf2df713b3cce94eb64876fea8f80c608e25130c18e4691be2b1dea56df8b772d26c0caca88231ef795125eb9678210c33bf20518c18e3047912ddb4b
|
|
||||||
SHA512 (packaging-21.3.tar.gz) = 2e3aa276a4229ac7dc0654d586799473ced9761a83aa4159660d37ae1a2a8f30e987248dd0e260e2834106b589f259a57ce9936eef0dcc3c430a99ac6b663e05
|
|
||||||
SHA512 (pyparsing-3.0.7.tar.gz) = 1e692f4cdaa6b6e8ca2729d0a3e2ba16d978f1957c538b6de3a4220ec7d996bdbe87c41c43abab851fffa3b0498a05841373e435602917b8c095042e273badb5
|
|
||||||
SHA512 (resolvelib-1.0.1.tar.gz) = 52c872fb2a22c47de022a661dc4d8de8c6af450f1cff6f2b99cd91bf7eccae5b6ee223793f50b9679c1c6caedbd8bb63330915ee6f10533b1a0ed239d068b36f
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
diff --git a/lib/ansible/plugins/loader.py b/lib/ansible/plugins/loader.py
|
|
||||||
index f3252d7142..1e4d3bca38 100644
|
|
||||||
--- a/lib/ansible/plugins/loader.py
|
|
||||||
+++ b/lib/ansible/plugins/loader.py
|
|
||||||
@@ -1532,7 +1532,7 @@ cache_loader = PluginLoader(
|
|
||||||
callback_loader = PluginLoader(
|
|
||||||
'CallbackModule',
|
|
||||||
'ansible.plugins.callback',
|
|
||||||
- C.DEFAULT_CALLBACK_PLUGIN_PATH,
|
|
||||||
+ C.DEFAULT_CALLBACK_PLUGIN_PATH + ['/usr/share/ansible/telemetry'],
|
|
||||||
'callback_plugins',
|
|
||||||
)
|
|
||||||
|
|
||||||
302
telemetry.py
302
telemetry.py
@ -1,302 +0,0 @@
|
|||||||
#! /usr/libexec/platform-python
|
|
||||||
# Copyright: Contributors to the Ansible project
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
name: telemetry
|
|
||||||
short_description: Track various telemetry related data and store in journald
|
|
||||||
description:
|
|
||||||
- Track various telemetry related data and store in journald
|
|
||||||
type: aggregate
|
|
||||||
options:
|
|
||||||
bypass_insights_check:
|
|
||||||
name: Bypass Insights Check
|
|
||||||
description: Bypass check to see if insights-client is active
|
|
||||||
default: false
|
|
||||||
type: bool
|
|
||||||
env:
|
|
||||||
- name: TELEMETRY_BYPASS_INSIGHTS_CHECK
|
|
||||||
notes:
|
|
||||||
- The file can also be executed directly from the CLI to retrieve
|
|
||||||
the stored telemetry data from journald
|
|
||||||
'''
|
|
||||||
|
|
||||||
import contextlib
|
|
||||||
import ctypes
|
|
||||||
import datetime
|
|
||||||
import functools
|
|
||||||
import importlib.util
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import pathlib
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import uuid
|
|
||||||
from collections import Counter, defaultdict
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# When run as a script via insights-client, these are not needed
|
|
||||||
CallbackBase = object
|
|
||||||
Display = None
|
|
||||||
else:
|
|
||||||
from ansible.executor.task_result import TaskResult
|
|
||||||
from ansible.module_utils.common.yaml import yaml_load
|
|
||||||
from ansible.plugins.callback import CallbackBase
|
|
||||||
from ansible.plugins.loader import connection_loader
|
|
||||||
from ansible.release import __version__ as ansible_version
|
|
||||||
from ansible.utils.display import Display
|
|
||||||
|
|
||||||
journal_sendv = None
|
|
||||||
try:
|
|
||||||
from systemd import journal
|
|
||||||
journal_sendv = journal.sendv
|
|
||||||
except ImportError:
|
|
||||||
# When invoked using the non-system python
|
|
||||||
# the systemd python bindings are not available
|
|
||||||
with contextlib.suppress(AttributeError, OSError):
|
|
||||||
_libsysetmd = ctypes.CDLL('libsystemd.so.0')
|
|
||||||
sd_journal_send = _libsysetmd.sd_journal_send
|
|
||||||
|
|
||||||
def journal_sendv(*args):
|
|
||||||
b_args = [ctypes.c_char_p(a.encode()) for a in args] + [None]
|
|
||||||
sd_journal_send(*b_args)
|
|
||||||
|
|
||||||
if sys.version_info >= (3, 10):
|
|
||||||
from importlib.resources import files
|
|
||||||
else:
|
|
||||||
# importlib.resources below Python 3.10 doesn't support
|
|
||||||
# custom loaders, this is not a full featured replacement
|
|
||||||
# but suffices for the needs of this plugin
|
|
||||||
def files(name):
|
|
||||||
spec = importlib.util.find_spec(name)
|
|
||||||
if spec is None:
|
|
||||||
raise ImportError(name)
|
|
||||||
origin = pathlib.Path(spec.origin)
|
|
||||||
if origin.name == '__synthetic__':
|
|
||||||
origin = origin.parent
|
|
||||||
return origin
|
|
||||||
|
|
||||||
if Display:
|
|
||||||
display = Display()
|
|
||||||
|
|
||||||
_CORE_SYN_COLLECTIONS = frozenset((
|
|
||||||
'ansible.builtin',
|
|
||||||
'ansible.legacy',
|
|
||||||
))
|
|
||||||
|
|
||||||
_CORE_FACT_MODULES = frozenset((
|
|
||||||
'setup',
|
|
||||||
'ansible.builtin.setup',
|
|
||||||
'ansible.legacy.setup',
|
|
||||||
'gather_facts',
|
|
||||||
'ansible.builtin.gather_facts',
|
|
||||||
'ansible.legacy.gather_facts',
|
|
||||||
))
|
|
||||||
|
|
||||||
_ANSIBLE_TELEMETRY_MESSAGE_ID = uuid.UUID('73df9e03d8c6473eb811065c4ebc370a')
|
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache(maxsize=None)
|
|
||||||
def _get_connection_fqcn(task, host):
|
|
||||||
connection = host.vars.get('ansible_connection')
|
|
||||||
if not connection:
|
|
||||||
connection = task.connection
|
|
||||||
is_connection_fqcn = '.' in connection
|
|
||||||
if is_connection_fqcn:
|
|
||||||
return connection
|
|
||||||
|
|
||||||
return connection_loader.get_with_context(
|
|
||||||
connection,
|
|
||||||
class_only=True,
|
|
||||||
collection_list=task.collections,
|
|
||||||
).plugin_load_context.resolved_fqcn
|
|
||||||
|
|
||||||
|
|
||||||
class CallbackModule(CallbackBase):
|
|
||||||
CALLBACK_VERSION = 2.0
|
|
||||||
CALLBACK_TYPE = 'aggregate'
|
|
||||||
CALLBACK_NAME = 'telemetry'
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.wants_implicit_tasks = False
|
|
||||||
self.disabled = False
|
|
||||||
|
|
||||||
self._telemetry = {
|
|
||||||
'collections': defaultdict(
|
|
||||||
lambda: {
|
|
||||||
'resources': defaultdict(
|
|
||||||
lambda: defaultdict(lambda: {
|
|
||||||
'count': 0,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
'version': '*',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
self._hosts = set()
|
|
||||||
self._os = {}
|
|
||||||
self._conn_cache = {}
|
|
||||||
|
|
||||||
def _is_insights_client_active(self):
|
|
||||||
if self.get_option('bypass_insights_check'):
|
|
||||||
return True
|
|
||||||
|
|
||||||
if not os.path.exists('/etc/insights-client/.registered'):
|
|
||||||
return False
|
|
||||||
|
|
||||||
with contextlib.suppress(subprocess.CalledProcessError):
|
|
||||||
subprocess.run(
|
|
||||||
['systemctl', 'is-active', '--quiet', 'insights-client.timer'],
|
|
||||||
capture_output=True,
|
|
||||||
check=True,
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _set_disabled(self):
|
|
||||||
if not self._is_insights_client_active():
|
|
||||||
return True
|
|
||||||
|
|
||||||
if journal_sendv is None:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def set_options(self, task_keys=None, var_options=None, direct=None):
|
|
||||||
super().set_options(task_keys=task_keys, var_options=var_options, direct=direct)
|
|
||||||
self.disabled = self._set_disabled()
|
|
||||||
|
|
||||||
def _track_os(self, host_name, result):
|
|
||||||
if host_name in self._os:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
af = result.get('ansible_facts')
|
|
||||||
except AttributeError:
|
|
||||||
return
|
|
||||||
|
|
||||||
if not af:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
os_name = '%(ansible_distribution)s-%(ansible_distribution_version)s' % af
|
|
||||||
except KeyError:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
self._os[host_name] = os_name
|
|
||||||
|
|
||||||
def _handle_result(self, *args, **kwargs):
|
|
||||||
if not args:
|
|
||||||
return
|
|
||||||
|
|
||||||
result = args[0]
|
|
||||||
if not isinstance(result, TaskResult):
|
|
||||||
return
|
|
||||||
|
|
||||||
host = result._host
|
|
||||||
host_name = host.get_name()
|
|
||||||
task = result._task
|
|
||||||
role = task._role
|
|
||||||
|
|
||||||
self._hosts.add(host_name)
|
|
||||||
|
|
||||||
action = task.resolved_action
|
|
||||||
action_collection = None
|
|
||||||
if action and '.' in action:
|
|
||||||
action_collection = '.'.join(action.split('.', 2)[:2])
|
|
||||||
|
|
||||||
if action in _CORE_FACT_MODULES:
|
|
||||||
self._track_os(host_name, result._result)
|
|
||||||
|
|
||||||
role_collection = None
|
|
||||||
role_name = None if not role else role.get_name()
|
|
||||||
if role and '.' in role_name:
|
|
||||||
role_collection = '.'.join(role_name.split('.', 2)[:2])
|
|
||||||
|
|
||||||
connection_collection = None
|
|
||||||
connection = _get_connection_fqcn(task, host)
|
|
||||||
if '.' in connection:
|
|
||||||
connection_collection = '.'.join(connection.split('.')[:2])
|
|
||||||
|
|
||||||
collections = self._telemetry['collections']
|
|
||||||
for resource, collection, name in (('action', action_collection, action),
|
|
||||||
('role', role_collection, role_name),
|
|
||||||
('connection', connection_collection, connection)):
|
|
||||||
if not collection:
|
|
||||||
continue
|
|
||||||
|
|
||||||
collections[collection]['resources'][resource][name]['count'] += 1
|
|
||||||
|
|
||||||
# v2_on_file_diff = _handle_result
|
|
||||||
v2_runner_item_on_failed = _handle_result
|
|
||||||
v2_runner_item_on_ok = _handle_result
|
|
||||||
v2_runner_item_on_skipped = _handle_result
|
|
||||||
v2_runner_on_async_failed = _handle_result
|
|
||||||
v2_runner_on_async_ok = _handle_result
|
|
||||||
v2_runner_on_async_poll = _handle_result
|
|
||||||
v2_runner_on_failed = _handle_result
|
|
||||||
v2_runner_on_ok = _handle_result
|
|
||||||
v2_runner_on_skipped = _handle_result
|
|
||||||
v2_runner_on_unreachable = _handle_result
|
|
||||||
v2_runner_retry = _handle_result
|
|
||||||
|
|
||||||
def v2_playbook_on_stats(self, stats):
|
|
||||||
self._telemetry['ansible_core'] = {
|
|
||||||
'version': ansible_version,
|
|
||||||
}
|
|
||||||
self._telemetry['hosts'] = {
|
|
||||||
'count': len(self._hosts),
|
|
||||||
'os': Counter(self._os.values()),
|
|
||||||
}
|
|
||||||
|
|
||||||
for collection in self._telemetry['collections']:
|
|
||||||
if collection in _CORE_SYN_COLLECTIONS:
|
|
||||||
continue
|
|
||||||
cpath = files('ansible_collections.%s' % collection)
|
|
||||||
for candidate in ('METADATA.json', 'galaxy.yml'):
|
|
||||||
mdfile = cpath.joinpath(candidate)
|
|
||||||
if mdfile.exists():
|
|
||||||
self._telemetry['collections'][collection]['version'] = yaml_load(
|
|
||||||
mdfile.read_text()
|
|
||||||
).get('version', '*')
|
|
||||||
break
|
|
||||||
|
|
||||||
with contextlib.suppress(Exception):
|
|
||||||
self._write_journal()
|
|
||||||
|
|
||||||
def _write_journal(self):
|
|
||||||
journal_sendv(
|
|
||||||
'MESSAGE=%s' % json.dumps(self._telemetry, separators=(',', ':')),
|
|
||||||
'MESSAGE_ID=%s' % _ANSIBLE_TELEMETRY_MESSAGE_ID.hex,
|
|
||||||
'ANSIBLE_TELEMETRY=core',
|
|
||||||
'ANSIBLE_TELEMETRY_ID=%s' % uuid.uuid4().hex,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def _get_journal_reader(seek=None):
|
|
||||||
with journal.Reader() as j:
|
|
||||||
if seek:
|
|
||||||
j.seek_realtime(seek)
|
|
||||||
j.add_match('MESSAGE_ID=%s' % _ANSIBLE_TELEMETRY_MESSAGE_ID.hex)
|
|
||||||
j.add_match('ANSIBLE_TELEMETRY=core')
|
|
||||||
yield j
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
lastupload_file = pathlib.Path('/etc/insights-client/.lastupload')
|
|
||||||
lastupload = None
|
|
||||||
with contextlib.suppress(ValueError, OSError):
|
|
||||||
lastupload = datetime.datetime.strptime(
|
|
||||||
lastupload_file.read_text(),
|
|
||||||
'%Y-%m-%dT%H:%M:%S.%f'
|
|
||||||
)
|
|
||||||
|
|
||||||
with _get_journal_reader(lastupload) as j:
|
|
||||||
for entry in j:
|
|
||||||
print(entry['MESSAGE'])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
- hosts: localhost
|
|
||||||
gather_facts: yes
|
|
||||||
roles:
|
|
||||||
- role: standard-test-basic
|
|
||||||
tags:
|
|
||||||
- classic
|
|
||||||
tests:
|
|
||||||
- simple:
|
|
||||||
dir: .
|
|
||||||
run: /usr/bin/ansible localhost -m dnf -a "list=installed"
|
|
||||||
# tasks:
|
|
||||||
# This is only used as part of rpm-ostree which has extensive tests
|
|
||||||
# and there is no point to testing it separately.
|
|
||||||
# - name: true
|
|
||||||
# shell: true
|
|
||||||
Loading…
Reference in New Issue
Block a user