Bug#1089106: bookworm-pu: package ansible-core/2.14.18-0+deb12u1
Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: ansible-core@packages.debian.org, debian@rocketjump.eu
Control: affects -1 + src:ansible-core
(Please provide enough information to help the release team
to judge the request efficiently. E.g. by filling in the
sections below.)
[ Reason ]
This is a bugfix-only update from ansible-core 2.14.16 to 2.14.18. This fixes
three CVEs:
* CVE-2024-11079
* CVE-2024-8775
* CVE-2024-9902
and few other bugfixes as seen here:
https://salsa.debian.org/python-team/packages/ansible-core/-/blob/debian/bookworm/changelogs/CHANGELOG-v2.14.rst?ref_type=heads#v2-14-18
[ Impact ]
Three security issues and various bugfixes won't be available to users.
[ Tests ]
I have backported the integration autopkgtests from the sid branch to bookworm
to ensure we have tests coverage for this and future security fixes.
[ Risks ]
Risks are low, as upstream has a good CI pipeline that covers most code.
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[x] the issue is verified as fixed in unstable
[ Changes ]
From the changelog:
[ Lee Garrett ]
* New stable bugfix release
* Add integration tests to autopkgtest
* Fix CVE-2024-11079: This vulnerability allows attackers to bypass unsafe
content protections using the hostvars object to reference and execute
templated content. This issue can lead to arbitrary code execution if remote
data or module outputs are improperly templated within playbooks.
[ Bastien Roucariès ]
* Fix CVE-2024-8775: A flaw was found in Ansible,
where sensitive information stored in Ansible Vault files can be exposed in
plaintext during the execution of a playbook. This occurs when using tasks
such as include_vars to load vaulted variables without setting the no_log:
true parameter, resulting in sensitive data being printed in the playbook
output or logs. This can lead to the unintentional disclosure of secrets
like passwords or API keys, compromising security and potentially allowing
unauthorized access or actions. (Closes: #1082851)
* Fix CVE-2024-9902: A flaw was found in Ansible.
The ansible-core `user` module can allow an unprivileged user to silently
create or replace the contents of any file on any system path and take
ownership of it when a privileged user executes the `user` module against
the unprivileged user's home directory. If the unprivileged user has
traversal permissions on the directory containing the exploited target file,
they retain full control over the contents of the file as its owner.
[ Other info ]
%
diff -Nru ansible-core-2.14.16/changelogs/CHANGELOG-v2.14.rst ansible-core-2.14.18/changelogs/CHANGELOG-v2.14.rst
--- ansible-core-2.14.16/changelogs/CHANGELOG-v2.14.rst 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/changelogs/CHANGELOG-v2.14.rst 2024-11-04 19:35:24.000000000 +0100
@@ -5,6 +5,51 @@
.. contents:: Topics
+v2.14.18
+========
+
+Release Summary
+---------------
+
+| Release Date: 2024-11-04
+| `Porting Guide <https://docs.ansible.com/ansible-core/2.14/porting_guides/porting_guide_core_2.14.html>`__
+
+
+Minor Changes
+-------------
+
+- ansible-test - Improve container runtime probe error handling. When unexpected probe output is encountered, an error with more useful debugging information is provided.
+- ansible-test - Removed support for provisioning remote Windows 2012 and 2012-R2 instances.
+- ansible-test - Removed the ``vyos/1.1.8`` network remote as it is no longer functional.
+- ansible-test - Update ``pypi-test-container`` to version 3.1.0.
+
+Security Fixes
+--------------
+
+- include_vars action - Ensure that result masking is correctly requested when vault-encrypted files are read. (CVE-2024-8775)
+- task result processing - Ensure that action-sourced result masking (``_ansible_no_log=True``) is preserved. (CVE-2024-8775)
+- user action won't allow ssh-keygen, chown and chmod to run on existing ssh public key file, avoiding traversal on existing symlinks (CVE-2024-9902).
+
+Bugfixes
+--------
+
+- user action will now require O(force) to overwrite the public part of an ssh key when generating ssh keys, as was already the case for the private part.
+
+v2.14.17
+========
+
+Release Summary
+---------------
+
+| Release Date: 2024-05-20
+| `Porting Guide <https://docs.ansible.com/ansible-core/2.14/porting_guides/porting_guide_core_2.14.html>`__
+
+
+Bugfixes
+--------
+
+- ansible-test - Automatically enable the PyPI proxy for the ``centos7`` container to restore the ability to use ``pip`` in that container.
+
v2.14.16
========
@@ -66,6 +111,7 @@
--------
- ``ansible-test sanity --test runtime-metadata`` - add ``action_plugin`` as a valid field for modules in the schema (https://github.com/ansible/ansible/pull/82562).
+- ansible-galaxy role install - fix symlinks (https://github.com/ansible/ansible/issues/82702, https://github.com/ansible/ansible/issues/81965).
- ansible-galaxy role install - normalize tarfile paths and symlinks using ``ansible.utils.path.unfrackpath`` and consider them valid as long as the realpath is in the tarfile's role directory (https://github.com/ansible/ansible/issues/81965).
- unsafe data - Enable directly using ``AnsibleUnsafeText`` with Python ``pathlib`` (https://github.com/ansible/ansible/issues/82414)
diff -Nru ansible-core-2.14.16/changelogs/changelog.yaml ansible-core-2.14.18/changelogs/changelog.yaml
--- ansible-core-2.14.16/changelogs/changelog.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/changelogs/changelog.yaml 2024-11-04 19:35:24.000000000 +0100
@@ -1016,6 +1016,8 @@
bugfixes:
- '``ansible-test sanity --test runtime-metadata`` - add ``action_plugin`` as
a valid field for modules in the schema (https://github.com/ansible/ansible/pull/82562).'
+ - ansible-galaxy role install - fix symlinks (https://github.com/ansible/ansible/issues/82702,
+ https://github.com/ansible/ansible/issues/81965).
- ansible-galaxy role install - normalize tarfile paths and symlinks using ``ansible.utils.path.unfrackpath``
and consider them valid as long as the realpath is in the tarfile's role directory
(https://github.com/ansible/ansible/issues/81965).
@@ -1102,6 +1104,79 @@
- 82574-ansible-test-ansible-doc-underscore.yml
- winrm-task-timeout.yml
release_date: '2024-04-16'
+ 2.14.17:
+ changes:
+ release_summary: '| Release Date: 2024-05-20
+
+ | `Porting Guide <https://docs.ansible.com/ansible-core/2.14/porting_guides/porting_guide_core_2.14.html>`__
+
+ '
+ codename: C'mon Everybody
+ fragments:
+ - 2.14.17_summary.yaml
+ release_date: '2024-05-20'
+ 2.14.17rc1:
+ changes:
+ bugfixes:
+ - ansible-test - Automatically enable the PyPI proxy for the ``centos7`` container
+ to restore the ability to use ``pip`` in that container.
+ release_summary: '| Release Date: 2024-05-13
+
+ | `Porting Guide <https://docs.ansible.com/ansible-core/2.14/porting_guides/porting_guide_core_2.14.html>`__
+
+ '
+ codename: C'mon Everybody
+ fragments:
+ - 2.14.17rc1_summary.yaml
+ - ansible-test-centos7-pypi-proxy.yml
+ release_date: '2024-05-13'
+ 2.14.18:
+ changes:
+ release_summary: '| Release Date: 2024-11-04
+
+ | `Porting Guide <https://docs.ansible.com/ansible-core/2.14/porting_guides/porting_guide_core_2.14.html>`__
+
+ '
+ codename: C'mon Everybody
+ fragments:
+ - 2.14.18_summary.yaml
+ release_date: '2024-11-04'
+ 2.14.18rc1:
+ changes:
+ bugfixes:
+ - user action will now require O(force) to overwrite the public part of an ssh
+ key when generating ssh keys, as was already the case for the private part.
+ minor_changes:
+ - ansible-test - Improve container runtime probe error handling. When unexpected
+ probe output is encountered, an error with more useful debugging information
+ is provided.
+ - ansible-test - Removed support for provisioning remote Windows 2012 and 2012-R2
+ instances.
+ - ansible-test - Removed the ``vyos/1.1.8`` network remote as it is no longer
+ functional.
+ - ansible-test - Update ``pypi-test-container`` to version 3.1.0.
+ release_summary: '| Release Date: 2024-10-29
+
+ | `Porting Guide <https://docs.ansible.com/ansible-core/2.14/porting_guides/porting_guide_core_2.14.html>`__
+
+ '
+ security_fixes:
+ - include_vars action - Ensure that result masking is correctly requested when
+ vault-encrypted files are read. (CVE-2024-8775)
+ - task result processing - Ensure that action-sourced result masking (``_ansible_no_log=True``)
+ is preserved. (CVE-2024-8775)
+ - user action won't allow ssh-keygen, chown and chmod to run on existing ssh
+ public key file, avoiding traversal on existing symlinks (CVE-2024-9902).
+ codename: C'mon Everybody
+ fragments:
+ - 2.14.18rc1_summary.yaml
+ - ansible-test-probe-error-handling.yml
+ - ansible-test-pypi-test-container-update.yml
+ - ansible-test-vyos.yml
+ - ansible-test-windows-2012.yml
+ - cve-2024-8775.yml
+ - user_ssh_fix.yml
+ release_date: '2024-10-29'
2.14.1rc1:
changes:
bugfixes:
diff -Nru ansible-core-2.14.16/debian/changelog ansible-core-2.14.18/debian/changelog
--- ansible-core-2.14.16/debian/changelog 2024-06-25 16:52:07.000000000 +0200
+++ ansible-core-2.14.18/debian/changelog 2024-12-04 18:12:49.000000000 +0100
@@ -1,3 +1,32 @@
+ansible-core (2.14.18-0+deb12u1) bookworm; urgency=medium
+
+ [ Lee Garrett ]
+ * New stable bugfix release
+ * Add integration tests to autopkgtest
+ * Fix CVE-2024-11079: This vulnerability allows attackers to bypass unsafe
+ content protections using the hostvars object to reference and execute
+ templated content. This issue can lead to arbitrary code execution if remote
+ data or module outputs are improperly templated within playbooks.
+
+ [ Bastien Roucariès ]
+ * Fix CVE-2024-8775: A flaw was found in Ansible,
+ where sensitive information stored in Ansible Vault files can be exposed in
+ plaintext during the execution of a playbook. This occurs when using tasks
+ such as include_vars to load vaulted variables without setting the no_log:
+ true parameter, resulting in sensitive data being printed in the playbook
+ output or logs. This can lead to the unintentional disclosure of secrets
+ like passwords or API keys, compromising security and potentially allowing
+ unauthorized access or actions. (Closes: #1082851)
+ * Fix CVE-2024-9902: A flaw was found in Ansible.
+ The ansible-core `user` module can allow an unprivileged user to silently
+ create or replace the contents of any file on any system path and take
+ ownership of it when a privileged user executes the `user` module against
+ the unprivileged user's home directory. If the unprivileged user has
+ traversal permissions on the directory containing the exploited target file,
+ they retain full control over the contents of the file as its owner.
+
+ -- Lee Garrett <debian@rocketjump.eu> Wed, 04 Dec 2024 18:12:49 +0100
+
ansible-core (2.14.16-0+deb12u1) bookworm; urgency=medium
* New stable release (Closes: #1070193)
diff -Nru ansible-core-2.14.16/debian/patches/0022-CVE-2024-11079.patch ansible-core-2.14.18/debian/patches/0022-CVE-2024-11079.patch
--- ansible-core-2.14.16/debian/patches/0022-CVE-2024-11079.patch 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/debian/patches/0022-CVE-2024-11079.patch 2024-12-04 18:12:49.000000000 +0100
@@ -0,0 +1,333 @@
+Description: Fix CVE-2024-11079 hostvars unsafe context
+ This vulnerability allows attackers to bypass unsafe content protections using
+ the hostvars object to reference and execute templated content. This issue can
+ lead to arbitrary code execution if remote data or module outputs are
+ improperly templated within playbooks.
+ .
+ This patch is based on the backport of the patch to ansible-core 2.16
+Origin: backport, https://github.com/ansible/ansible/pull/84353
+Bug: https://github.com/ansible/ansible/pull/84339
+Bug-Debian: https://bugs.debian.org/1088106
+Reviewed-by: Lee Garrett <debian@rocketjump.eu>
+Last-Update: 2024-12-04
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- /dev/null
++++ b/changelogs/fragments/unsafe_hostvars_fix.yml
+@@ -0,0 +1,2 @@
++security_fixes:
++ - Templating will not prefer AnsibleUnsafe when a variable is referenced via hostvars - CVE-2024-11079
+--- a/lib/ansible/template/__init__.py
++++ b/lib/ansible/template/__init__.py
+@@ -49,7 +49,7 @@
+ from ansible.module_utils._text import to_native, to_text, to_bytes
+ from ansible.module_utils.common.collections import is_sequence
+ from ansible.plugins.loader import filter_loader, lookup_loader, test_loader
+-from ansible.template.native_helpers import ansible_native_concat, ansible_eval_concat, ansible_concat
++from ansible.template.native_helpers import AnsibleUndefined, ansible_native_concat, ansible_eval_concat, ansible_concat
+ from ansible.template.template import AnsibleJ2Template
+ from ansible.template.vars import AnsibleJ2Vars
+ from ansible.utils.display import Display
+@@ -296,35 +296,6 @@
+ return _update_wrapper(wrapper, func)
+
+
+-class AnsibleUndefined(StrictUndefined):
+- '''
+- A custom Undefined class, which returns further Undefined objects on access,
+- rather than throwing an exception.
+- '''
+- def __getattr__(self, name):
+- if name == '__UNSAFE__':
+- # AnsibleUndefined should never be assumed to be unsafe
+- # This prevents ``hasattr(val, '__UNSAFE__')`` from evaluating to ``True``
+- raise AttributeError(name)
+- # Return original Undefined object to preserve the first failure context
+- return self
+-
+- def __getitem__(self, key):
+- # Return original Undefined object to preserve the first failure context
+- return self
+-
+- def __repr__(self):
+- return 'AnsibleUndefined(hint={0!r}, obj={1!r}, name={2!r})'.format(
+- self._undefined_hint,
+- self._undefined_obj,
+- self._undefined_name
+- )
+-
+- def __contains__(self, item):
+- # Return original Undefined object to preserve the first failure context
+- return self
+-
+-
+ class AnsibleContext(Context):
+ '''
+ A custom context, which intercepts resolve_or_missing() calls and sets a flag
+--- a/lib/ansible/template/native_helpers.py
++++ b/lib/ansible/template/native_helpers.py
+@@ -7,13 +7,19 @@
+
+
+ import ast
++from collections.abc import Mapping
+ from itertools import islice, chain
+ from types import GeneratorType
+
++from ansible.module_utils.common.collections import is_sequence
+ from ansible.module_utils._text import to_text
+ from ansible.module_utils.six import string_types
+ from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
+ from ansible.utils.native_jinja import NativeJinjaText
++from ansible.utils.unsafe_proxy import wrap_var
++import ansible.module_utils.compat.typing as t
++
++from jinja2.runtime import StrictUndefined
+
+
+ _JSON_MAP = {
+@@ -30,6 +36,40 @@
+ return ast.Constant(value=_JSON_MAP[node.id])
+
+
++def _is_unsafe(value: t.Any) -> bool:
++ """
++ Our helper function, which will also recursively check dict and
++ list entries due to the fact that they may be repr'd and contain
++ a key or value which contains jinja2 syntax and would otherwise
++ lose the AnsibleUnsafe value.
++ """
++ to_check = [value]
++ seen = set()
++
++ while True:
++ if not to_check:
++ break
++
++ val = to_check.pop(0)
++ val_id = id(val)
++
++ if val_id in seen:
++ continue
++ seen.add(val_id)
++
++ if isinstance(val, AnsibleUndefined):
++ continue
++ if isinstance(val, Mapping):
++ to_check.extend(val.keys())
++ to_check.extend(val.values())
++ elif is_sequence(val):
++ to_check.extend(val)
++ elif getattr(val, '__UNSAFE__', False):
++ return True
++
++ return False
++
++
+ def ansible_eval_concat(nodes):
+ """Return a string of concatenated compiled nodes. Throw an undefined error
+ if any of the nodes is undefined.
+@@ -45,17 +85,28 @@
+ if not head:
+ return ''
+
++ unsafe = False
++
+ if len(head) == 1:
+ out = head[0]
+
+ if isinstance(out, NativeJinjaText):
+ return out
+
++ unsafe = _is_unsafe(out)
+ out = to_text(out)
+ else:
+ if isinstance(nodes, GeneratorType):
+ nodes = chain(head, nodes)
+- out = ''.join([to_text(v) for v in nodes])
++
++ out_values = []
++ for v in nodes:
++ if not unsafe and _is_unsafe(v):
++ unsafe = True
++
++ out_values.append(to_text(v))
++
++ out = ''.join(out_values)
+
+ # if this looks like a dictionary, list or bool, convert it to such
+ if out.startswith(('{', '[')) or out in ('True', 'False'):
+@@ -70,6 +121,9 @@
+ except (ValueError, SyntaxError, MemoryError):
+ pass
+
++ if unsafe:
++ out = wrap_var(out)
++
+ return out
+
+
+@@ -80,7 +134,19 @@
+
+ Used in Templar.template() when jinja2_native=False and convert_data=False.
+ """
+- return ''.join([to_text(v) for v in nodes])
++ unsafe = False
++ values = []
++ for v in nodes:
++ if not unsafe and _is_unsafe(v):
++ unsafe = True
++
++ values.append(to_text(v))
++
++ out = ''.join(values)
++ if unsafe:
++ out = wrap_var(out)
++
++ return out
+
+
+ def ansible_native_concat(nodes):
+@@ -97,6 +163,8 @@
+ if not head:
+ return None
+
++ unsafe = False
++
+ if len(head) == 1:
+ out = head[0]
+
+@@ -117,10 +185,21 @@
+ # short-circuit literal_eval for anything other than strings
+ if not isinstance(out, string_types):
+ return out
++
++ unsafe = _is_unsafe(out)
++
+ else:
+ if isinstance(nodes, GeneratorType):
+ nodes = chain(head, nodes)
+- out = ''.join([to_text(v) for v in nodes])
++
++ out_values = []
++ for v in nodes:
++ if not unsafe and _is_unsafe(v):
++ unsafe = True
++
++ out_values.append(to_text(v))
++
++ out = ''.join(out_values)
+
+ try:
+ evaled = ast.literal_eval(
+@@ -130,10 +209,45 @@
+ ast.parse(out, mode='eval')
+ )
+ except (ValueError, SyntaxError, MemoryError):
++ if unsafe:
++ out = wrap_var(out)
++
+ return out
+
+ if isinstance(evaled, string_types):
+ quote = out[0]
+- return f'{quote}{evaled}{quote}'
++ evaled = f'{quote}{evaled}{quote}'
++
++ if unsafe:
++ evaled = wrap_var(evaled)
+
+ return evaled
++
++
++class AnsibleUndefined(StrictUndefined):
++ """
++ A custom Undefined class, which returns further Undefined objects on access,
++ rather than throwing an exception.
++ """
++ def __getattr__(self, name):
++ if name == '__UNSAFE__':
++ # AnsibleUndefined should never be assumed to be unsafe
++ # This prevents ``hasattr(val, '__UNSAFE__')`` from evaluating to ``True``
++ raise AttributeError(name)
++ # Return original Undefined object to preserve the first failure context
++ return self
++
++ def __getitem__(self, key):
++ # Return original Undefined object to preserve the first failure context
++ return self
++
++ def __repr__(self):
++ return 'AnsibleUndefined(hint={0!r}, obj={1!r}, name={2!r})'.format(
++ self._undefined_hint,
++ self._undefined_obj,
++ self._undefined_name
++ )
++
++ def __contains__(self, item):
++ # Return original Undefined object to preserve the first failure context
++ return self
+--- a/lib/ansible/vars/hostvars.py
++++ b/lib/ansible/vars/hostvars.py
+@@ -110,11 +110,12 @@
+ return self._find_host(host_name) is not None
+
+ def __iter__(self):
+- for host in self._inventory.hosts:
+- yield host
++ # include implicit localhost only if it has variables set
++ yield from self._inventory.hosts | {'localhost': self._inventory.localhost} if self._inventory.localhost else {}
+
+ def __len__(self):
+- return len(self._inventory.hosts)
++ # include implicit localhost only if it has variables set
++ return len(self._inventory.hosts) + (1 if self._inventory.localhost else 0)
+
+ def __repr__(self):
+ out = {}
+--- /dev/null
++++ b/test/integration/targets/template/cve-2024-11079.yml
+@@ -0,0 +1,30 @@
++- name: test CVE-2024-11079 loop variables preserve unsafe hostvars
++ hosts: localhost
++ gather_facts: false
++ tasks:
++ - set_fact:
++ foo:
++ safe:
++ prop: '{{ "{{" }} unsafe_var {{ "}}" }}'
++ unsafe:
++ prop: !unsafe '{{ unsafe_var }}'
++
++ - name: safe var through hostvars loop is templated
++ assert:
++ that:
++ - item.prop == expected
++ loop:
++ - "{{ hostvars['localhost']['foo']['safe'] }}"
++ vars:
++ unsafe_var: bar
++ expected: bar
++
++ - name: unsafe var through hostvars loop is not templated
++ assert:
++ that:
++ - item.prop == expected
++ loop:
++ - "{{ hostvars['localhost']['foo']['unsafe'] }}"
++ vars:
++ unsafe_var: bar
++ expected: !unsafe '{{ unsafe_var }}'
+--- a/test/integration/targets/template/runme.sh
++++ b/test/integration/targets/template/runme.sh
+@@ -38,6 +38,10 @@
+ # ensure unsafe is preserved, even with extra newlines
+ ansible-playbook unsafe.yml -v "$@"
+
++# CVE 2024-11079
++ANSIBLE_JINJA2_NATIVE=true ansible-playbook cve-2024-11079.yml -v "$@"
++ANSIBLE_JINJA2_NATIVE=false ansible-playbook cve-2024-11079.yml -v "$@"
++
+ # ensure Jinja2 overrides from a template are used
+ ansible-playbook in_template_overrides.yml -v "$@"
+
diff -Nru ansible-core-2.14.16/debian/patches/series ansible-core-2.14.18/debian/patches/series
--- ansible-core-2.14.16/debian/patches/series 2024-06-25 15:35:56.000000000 +0200
+++ ansible-core-2.14.18/debian/patches/series 2024-12-04 18:12:49.000000000 +0100
@@ -1,3 +1,4 @@
0005-use-py3.patch
0009-resolvelib_compat.patch
0010-fix-facter.patch
+0022-CVE-2024-11079.patch
diff -Nru ansible-core-2.14.16/debian/salsa-ci.yml ansible-core-2.14.18/debian/salsa-ci.yml
--- ansible-core-2.14.16/debian/salsa-ci.yml 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/debian/salsa-ci.yml 2024-12-04 18:12:49.000000000 +0100
@@ -0,0 +1,6 @@
+include:
+ - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
+
+variables:
+ RELEASE: 'bookworm'
+ SALSA_CI_IMAGES_LINTIAN: "${SALSA_CI_IMAGES}/lintian:bookworm"
diff -Nru ansible-core-2.14.16/debian/tests/ansible-test-integration.py ansible-core-2.14.18/debian/tests/ansible-test-integration.py
--- ansible-core-2.14.16/debian/tests/ansible-test-integration.py 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/debian/tests/ansible-test-integration.py 2024-12-04 18:12:49.000000000 +0100
@@ -0,0 +1,422 @@
+#!/usr/bin/python3
+
+import argparse
+import os
+import subprocess
+import sys
+import time
+
+# helper function to print log messages depending on verbosity
+def log (level, *msg):
+ if args.verbose >= level:
+ print(' '.join([str(x) for x in msg]), flush=True)
+
+sys.dont_write_bytecode = True
+
+# helper function to run and log processes
+def runprog (name, progargs, env=None, exit_on_failure=True):
+ log(1, 'Running', name)
+ proc = subprocess.run(
+ progargs,
+ timeout = 300,
+ capture_output = True,
+ text = True,
+ env = env,
+ )
+ if proc.returncode != 0:
+ log(0,"#"*72)
+ log(0,'Running', name, 'failed!')
+ log(0,"Returncode:", proc.returncode)
+ log(1,"#### STDOUT ####")
+ log(1, proc.stdout)
+ log(1, "#### STDERR ####")
+ log(1, proc.stderr)
+ log(0,"#"*72)
+ if exit_on_failure:
+ sys.exit(proc.returncode)
+ return proc
+
+def locale_debug(name):
+ if args.verbose >= 3:
+ log(2, name)
+ log(2, 'output of /usr/bin/locale:')
+ subprocess.run(['/usr/bin/locale'])
+ prog = runprog('cat /etc/default/locale', ['cat', '/etc/default/locale'])
+ log(2, prog.stdout, prog.stderr)
+ # grep will exit 1 when it doesn't return anything, so don't fail on it.
+ prog = runprog(
+ 'grep -v -P \'^#|^$\' /etc/locale.gen',
+ ['grep', '-v', '-P', '^#|^$', '/etc/locale.gen'],
+ exit_on_failure=False,
+ )
+ log(2, prog.stdout, prog.stderr)
+
+parser = argparse.ArgumentParser(
+ prog='ansible-test-integration.py',
+ description='python script to run ansible-test integration against the Debian source package',
+)
+
+# Whether to run the default tests not in any other list
+parser.add_argument(
+ '--default-tests',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Run the default tests not listed anywhere else. (default: no)',
+)
+
+parser.add_argument(
+ '--requires-root',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Run tests that require root. (default: no)',
+)
+
+parser.add_argument(
+ '--requires-ssh',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Run tests that require a specially configured SSH server. (default: no)'
+)
+
+parser.add_argument(
+ '--requires-apt-mark-manual',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Run tests that do "apt-mark manual" on certain packages. (default: no)',
+)
+
+parser.add_argument(
+ '--fails-on-pip',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Run tests that run "pip3 install" on certain modules. (default: no)',
+)
+
+parser.add_argument(
+ '--failing',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Run tests that fail on other reasons. (default: no)',
+)
+
+parser.add_argument(
+ '--setup',
+ action=argparse.BooleanOptionalAction,
+ default=True,
+ help='Setup testbed via sudo. (default: yes)',
+)
+
+parser.add_argument(
+ '--dry-run',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Print the list of targets without actually running them',
+)
+
+parser.add_argument(
+ '--check-test-lists',
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help='Check if all the hardcoded integration tests from the other \
+ flags (e.g. --requires-root, --failing, ,etc.) still exist \
+ in the ansible-core test suite. Defaults to no. When set, \
+ skips everything else.',
+)
+parser.add_argument(
+ '--verbose', '-v',
+ action='count',
+ default=1,
+ help='verbosity between 0 and 5. 0 will only emit errors. 1=INFO. \
+ More for increasing levels of debug info. Defaults to 1.',
+)
+
+args = parser.parse_args()
+
+# Don't set up test env when checking test lists
+if args.check_test_lists:
+ args.setup = False
+
+locale_debug('locale before setting os.environ:')
+os.environ['LANG'] = 'en_US.UTF-8'
+locale_debug('locale after setting os.environ:')
+
+if args.setup is True:
+ proc = runprog('testbed-setup.sh', ['sudo', './debian/tests/testbed-setup.sh'])
+ log(2,"#### STDOUT ####")
+ log(2, proc.stdout)
+ log(2, "#### STDERR ####")
+ log(2, proc.stderr)
+ locale_debug('locale after running testbed-setup.sh:')
+
+# integration tests requiring root in some form
+integration_requires_root = {
+ 'ansible-test-container', # has needs/root in aliases file
+ 'ansible-vault', # https://github.com/ansible/ansible/issues/83837
+ 'any_errors_fatal', # PermissionError: [Errno 13] Permission denied: '/tmp/autopkgtest.EkgNeu/build.sJ3/real-tree/test/results/.tmp/output_dir/venv'
+ 'apt_key', # add/removes apt keys
+ 'become', # calls setup_test_user
+ 'blockinfile', # setup_remote_tmp_dir handler fails (hidden output)
+ 'callback_default', # checks for an error that has root's homedir
+ 'changed_when', # PermissionError: [Errno 13] Permission denied: b'/tmp/autopkgtest.EkgNeu/build.sJ3/real-tree/test/results/data/integration-2024-08-14-23-14-30.json'
+ 'copy', # has needs/root in aliases file
+ 'cron', # installs packages via setup_cron
+ 'debconf', # Writes to debconf database
+ 'dpkg_selections', # needs root to use dpkg
+ 'facts_linux_network', # has needs/root in aliases file
+ 'file', # has needs/root in aliases file
+ 'filter_core', # calls setup_test_user
+ 'find', # calls setup_test_user, has needs/root in aliases file
+ 'gathering_facts', # has needs/root in aliases file
+ 'gathering', # writes to /etc/ansible/facts.d/
+ 'group', # wants to add/remove systemd groups
+ 'hardware_facts', # creates and destroys logical volumes
+ 'keyword_inheritance', # calls setup_test_user
+ 'lookup_password', # calls setup_test_user
+ 'lookup_unvault', # has needs/root in aliases file
+ #'module_defaults', # requires sudo
+ 'module_utils', # calls setup_test_user, has needs/root in aliases file
+ 'noexec', # calls mount
+ 'old_style_cache_plugins', # has needs/root in aliases file
+ 'omit', # calls setup_test_user
+ 'package', # touches /usr/bin/
+ 'pip', # has needs/root in aliases file
+ 'raw', # uses 'su' as become method and doesn't pass a password
+ 'reboot', # has needs/root in aliases file
+ 'service', # requires root to create/start/stop services
+ 'slurp', # calls setup_test_user
+ 'systemd', # disables/enables services
+ 'template', # has needs/root in aliases file
+ 'unsafe_writes', # has needs/root in aliases file
+ 'user', # has needs/root in aliases file
+}
+
+# integration tests requiring a running ssh server
+integration_requires_ssh = {
+ 'become_unprivileged',
+ 'cli',
+ 'connection_paramiko_ssh',
+ 'connection_ssh',
+ 'delegate_to',
+ 'fetch',
+ 'module_tracebacks',
+}
+
+# integration tests requiring root because the apt module is used to
+# install missing packages, or to mark packages as manually installed
+integration_requires_apt_mark_manual = {
+ #'ansible-galaxy-collection-scm', # apt-mark manual git
+ 'ansible-pull', # apt-mark manual git
+ #'debconf', # apt-mark manual debconf-utils
+ 'iptables', # apt-mark manual iptables
+ 'git', # apt-mark manual git
+}
+
+integration_fails_on_pip = {
+ 'ansible-galaxy-collection-cli', # fails on pip
+ 'ansible-inventory', # pip error: externally-managed-environment ## upstream fix
+ 'builtin_vars_prompt', # passlib: pip error: externally-managed-environment
+ 'debugger', # pip installs pexpect
+ 'pause', # pip installs pexpect
+}
+
+integration_failing = {
+ 'ansible-galaxy-collection-scm': "ansible-core on PyPI depends on resolvelib<1.1.0",
+ 'ansible-galaxy-role': 'dict object has no attribute lnk_source', ## needs upstream fix?
+ 'ansible-test-docker': "pwsh doesn't exist in Debian yet",
+ 'ansible-test': 'installs and runs python libs from remote',
+ 'ansible-test-installed': 'checks only valid if source tree has bin/ directory',
+ 'ansible-test-sanity': 'checks are only valid for the source tree',
+ 'ansible-test-units-forked': '?????',
+ 'ansible-test-vendoring': 'Should test with ./bin/ansible-test which was removed in v2.18.0', ## needs upstream fix
+ 'become_su': 'This looks like a false positive, needs upstream confirmation',
+ 'copy': 'requires /root/.ssh/authorized_keys to exist',
+ 'facts_d': 'seems to read an unreadable problem without error', ## needs upstream fix
+ 'infra': 'requires hacking/test-module.py not present',
+ 'interpreter_discovery_python': 'detects /usr/bin/python3.11, expect python3, detects os_version 12.6, expects it to compare > 10',
+ 'packaging_cli-doc': 'checks only valid if source tree has bin/ directory',
+ 'remote_tmp': 'Will often show false positive on: "Test tempdir is removed", needs upstream fixing',
+ 'service_facts': "Version comparison failed: '<' not supported between instances of 'str' and 'int'", # writes to /usr/sbin/
+ 'template_jinja2_non_native': 'no need to test against latest jinja2',
+
+ # tests failing in bookworm, not going to fix them here unless future patches touch those code paths.
+ 'ansible-galaxy': "hardcoded root; filed MR with upstream",
+ 'apt': "requires deb-src lines; filed MR with upstream",
+ 'hostname': "requires upstream fixes; filed MR with upstream",
+ 'subversion': "sets up a svn repo via apache2 incorrectly; needs upstream fix",
+ 'unarchive': "tries to install non-existing package language-pack-fr; needs upstream fix",
+}
+
+if subprocess.check_output(['dpkg', '--print-architecture'], text=True).rstrip('\n') not in {'amd64', 'ppc64el'}:
+ integration_failing['binary_modules_posix'] = 'needs statically-built helloworld_linux_* from ci-files.testing.ansible.com'
+
+# work around autopkgtest providing the source tree owned by a different user
+if args.setup:
+ runprog('git config hack for normal user', ['git', 'config', '--global', '--add', 'safe.directory', '*'])
+ runprog('git config hack for root', ['sudo', 'git', 'config', '--global', '--add', 'safe.directory', '*'])
+
+pyver = str(sys.version_info.major) + '.' + str(sys.version_info.minor)
+
+overall_test_rc = 0
+failed_tests = []
+succeeded_tests = []
+
+# retrieve a list of all integration tests
+all_targets_cmd = runprog(
+ 'ansible-test to retrieve list of targets',
+ ['ansible-test', 'integration', '--list-targets', '--allow-root', '--allow-destructive'],
+ env={**os.environ, 'PYTHONPATH': os.path.join(os.getcwd(), 'test', 'lib')},
+)
+
+# Compile list of all targets
+all_targets = set(all_targets_cmd.stdout.splitlines())
+
+default_targets = list(
+ all_targets
+ - integration_requires_root
+ - integration_requires_ssh
+ - integration_requires_apt_mark_manual
+ - integration_fails_on_pip
+ - set(integration_failing.keys())
+)
+
+def check_if_list_in_all_targets( l1, name):
+ l = l1 - all_targets
+ global overall_test_rc # hack to change it out of func
+ if len(l) !=0:
+ log(0, name, 'has elements not in all_targets list!')
+ for i in l:
+ log(0, ' ', i)
+ overall_test_rc = 1
+ log(0, ' ^^^^ consider removing those.')
+ else:
+ log(0, name, 'looks good.')
+
+if args.check_test_lists:
+ check_if_list_in_all_targets(integration_requires_root, 'integration_requires_root')
+ check_if_list_in_all_targets(integration_requires_ssh, 'integration_requires_ssh')
+ check_if_list_in_all_targets(integration_requires_apt_mark_manual, 'integration_requires_apt_mark_manual')
+ check_if_list_in_all_targets(integration_fails_on_pip, 'integration_fails_on_pip')
+ check_if_list_in_all_targets(integration_failing.keys(), 'integration_failing')
+ sys.exit(overall_test_rc)
+
+# compile a list of targets to run, depending on CLI parameters
+targets = []
+skipped = []
+
+if args.default_tests is True:
+ targets.extend(default_targets)
+else:
+ skipped.extend(default_targets)
+
+if args.requires_root is True:
+ targets.extend(integration_requires_root)
+else:
+ skipped.extend(integration_requires_root)
+
+if args.requires_ssh is True:
+ targets.extend(integration_requires_ssh)
+else:
+ skipped.extend(integration_requires_ssh)
+
+if args.requires_apt_mark_manual is True:
+ targets.extend(integration_requires_apt_mark_manual)
+else:
+ skipped.extend(integration_requires_apt_mark_manual)
+
+if args.fails_on_pip is True:
+ targets.extend(integration_fails_on_pip)
+else:
+ skipped.extend(integration_fails_on_pip)
+
+if args.failing is True:
+ targets.extend(integration_failing)
+else:
+ skipped.extend(integration_failing)
+
+targets.sort()
+skipped.sort()
+
+for i in targets:
+
+ if args.dry_run is True:
+ log(1, 'Would run ansible-test in', i)
+ skipped.append(i)
+ continue
+
+ print ("\n" + "#"*72, flush=True)
+ print ("#### Running integration tests in", i, flush=True)
+ print ("#"*72, flush=True)
+
+ cmdlist = [
+ 'ansible-test',
+ 'integration',
+ '--allow-root',
+ '--allow-destructive',
+ '--venv-system-site-packages',
+ '--python-interpreter',
+ '/usr/bin/python3',
+ '--python',
+ pyver,
+ '--local',
+ '--color', 'yes',
+ i
+ ]
+
+ env={
+ **os.environ,
+ 'PYTHONPATH': os.path.join(os.getcwd(), 'test', 'lib'),
+ }
+
+
+ if i in integration_requires_root:
+ cmdlist = ['sudo', '--preserve-env=PYTHONPATH'] + cmdlist
+
+ # For debugging permission errors on writing results output
+ if args.verbose >= 3:
+ subprocess.run(['ls', '-ld', './test/'])
+ subprocess.run(['ls', '-ld', './test/results/'])
+ subprocess.run(['ls', '-ld', './test/results/.tmp/'])
+ subprocess.run(['ls', '-ld', './test/results/.tmp/output_dir/'])
+
+ # fix any permission errors due to some root tests not cleaning up correctly
+ subprocess.run(['sudo', 'chown', '-R', 'user:user', './test'])
+
+ start = time.time()
+ proc = subprocess.run(cmdlist, env=env)
+ end = time.time()
+
+ if proc.returncode != 0:
+ failed_tests.append({
+ 'name': i,
+ 'time': int( end - start)
+ })
+ overall_test_rc = proc.returncode
+ else:
+ succeeded_tests.append({
+ 'name': i,
+ 'time': int( end - start)
+ })
+
+if overall_test_rc != 0:
+ print ("#"*72, flush=True)
+ print ("#### failed tests are:", flush=True)
+ for i in failed_tests:
+ print ("####", i['name'], flush=True)
+ print ("#"*72, flush=True)
+
+log(1, '### TEST SUMMARY ###')
+log(1, 'succeeded tests:', len(succeeded_tests))
+log(1, 'failed tests:', len(failed_tests))
+log(1, 'skipped tests:', len(skipped))
+
+log(2, '### succeeded test list:')
+for i in succeeded_tests:
+ log(2, '{:<30} (elapsed time: {:>3}s)'.format( i['name'], i['time'] ) )
+log(2, '### failed test list:')
+for i in failed_tests:
+ log(2, '{:<30} (elapsed time: {:>3}s)'.format( i['name'], i['time'] ) )
+log(2, '### skipped test list:')
+for i in skipped:
+ log(2, i)
+
+sys.exit(overall_test_rc)
diff -Nru ansible-core-2.14.16/debian/tests/control ansible-core-2.14.18/debian/tests/control
--- ansible-core-2.14.16/debian/tests/control 2024-06-25 15:35:56.000000000 +0200
+++ ansible-core-2.14.18/debian/tests/control 2024-12-04 18:12:49.000000000 +0100
@@ -17,3 +17,86 @@
python3-tz,
python3-winrm,
python3-yaml
+
+# integration tests that can run as unprivileged user + with sudo
+Test-Command: ./debian/tests/ansible-test-integration.py --default-tests --requires-apt-mark-manual --requires-root
+Features: test-name=ansible-test-integration-default
+Depends: @,
+ acl, # lineinfile integration test
+ apache2-utils, # used by subversion integration test
+ bash, # Many scripts have bash shebangs
+ cargo, # needed to build cryptography on some architectures, which some tests install from PyPI
+ debconf-utils, # debconf
+ equivs, # integration test "apt"
+ file, # stat
+ gcc, # needed to build cffi on some architectures, which some tests install from PyPI
+ git, # used by most tests
+ gnupg, # integration test apt_key
+ gzip, # integration test git
+ iptables, # integration test iptables
+ libffi-dev, # needed to build cffi on some architectures, which some tests install from PyPI
+ libfile-fcntllock-perl, # integration test "apt"
+ libssl-dev, # needed to build cryptography on some architectures, which some tests install from PyPI
+ libyaml-dev, # needed to build PyYAML on some architectures, which some tests install from PyPI
+ locales,
+ lvm2, # integration test hardware_facts
+ openssl, # integration test ansible-galaxy
+ pkg-config, # needed to build cryptography on some architectures, which some tests install from PyPI
+ python3-apt, # needed for checking if packages are installed
+ python3-dev, # needed to build cffi on some architectures, which some tests install from PyPI
+ python3-distlib, # ansible-galaxy-collection-cli
+ python3-passlib, # grep 'setup/always/setup_passlib' test/integration/targets/*/aliases
+ python3-pexpect, # grep 'setup/always/setup_pexpect' test/integration/targets/*/aliases
+ python3-pip, # ansible-test-config, builtin_vars_prompt, remove again and fix tests
+ python3-pytest, # ansible-test-units-assertions
+ python3-pytest-mock, # ansible-test-units-assertions
+ python3-setuptools, # integration test "pip"
+ python3-venv, # ansible-inventory; ./test/lib/ansible_test/_util/target/injector/virtualenv.sh
+ python3-virtualenv, # ansible-inventory, ansible-test-installed; ./test/lib/ansible_test/_util/target/injector/virtualenv.sh
+ python3-yaml, # ansible-test-units-forked
+ sudo, # needed for testbed-setup.sh
+ tar, # integration test git
+ unzip, # integration test git
+ zip, # integration test git
+Restrictions:
+ allow-stderr, # lots of STDERR output
+ breaks-testbed, # many tests add/delete files, or change the system in fundamental ways
+ needs-internet, # used for ansible-galaxy and pip tests
+ needs-sudo, # used to call testbed-setup.sh
+
+# integration tests that fail on some variation of running pip install
+Test-Command: ./debian/tests/ansible-test-integration.py --fails-on-pip
+Features: test-name=ansible-test-integration-fails-on-pip
+Depends: @,
+ git,
+ locales,
+ python3-passlib, # grep 'setup/always/setup_passlib' test/integration/targets/*/aliases
+ python3-pexpect, # grep 'setup/always/setup_pexpect' test/integration/targets/*/aliases
+ python3-pip, # ansible-test-config, builtin_vars_prompt, remove again and fix tests
+Restrictions:
+ allow-stderr, # lots of STDERR output
+ flaky, # known to be broken
+ needs-internet, # used for ansible-galaxy and pip tests
+ needs-sudo, # used to call testbed-setup.sh
+ # don't run broken tests on CI, as that makes autopkgtest time out
+ # Run `autopkgtest --ignore-restrictions disabled-on-ci [...]` to run locally.
+ # Thanks elbrus for the tip!
+ disabled-on-ci,
+
+# integration tests that fail for other reasons
+Test-Command: ./debian/tests/ansible-test-integration.py --failing
+Features: test-name=ansible-test-integration-failing
+Depends: @,
+ git,
+ locales,
+ python3-passlib, # grep 'setup/always/setup_passlib' test/integration/targets/*/aliases
+ python3-pexpect, # grep 'setup/always/setup_pexpect' test/integration/targets/*/aliases
+ python3-pip, # ansible-test-config, builtin_vars_prompt, remove again and fix tests
+ shellcheck, # ansible-test-docker
+Restrictions:
+ allow-stderr, # lots of STDERR output
+ flaky, # known to be broken
+ needs-internet, # used for ansible-galaxy and pip tests
+ needs-sudo, # used to call testbed-setup.sh
+ # don't run broken tests on CI
+ disabled-on-ci,
diff -Nru ansible-core-2.14.16/debian/tests/testbed-setup.sh ansible-core-2.14.18/debian/tests/testbed-setup.sh
--- ansible-core-2.14.16/debian/tests/testbed-setup.sh 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/debian/tests/testbed-setup.sh 2024-12-04 18:12:49.000000000 +0100
@@ -0,0 +1,42 @@
+#!/usr/bin/sh
+
+# helper script called from within ansible-test-integration.py to
+
+set -eu
+
+# workaround for various integration tests trying to do this and failing
+# due to missing root permission
+echo 'apt-mark changes'
+/usr/bin/apt-mark manual debconf-utils || true
+/usr/bin/apt-mark manual equivs || true
+/usr/bin/apt-mark manual git || true
+/usr/bin/apt-mark manual iptables || true
+/usr/bin/apt-mark manual libfile-fcntllock-perl || true
+/usr/bin/apt-mark manual openssl || true
+/usr/bin/apt-mark manual python3-distlib || true
+
+# Set default locale to en_US.UTF-8 to remove lots of warnings when
+# running the tests
+echo 'debconf selection changes'
+# These values get overwritten by what is in the config files when
+# running dpkg-reconfigure, see https://bugs.debian.org/684134
+cat << EOF | debconf-set-selections
+locales locales/default_environment_locale select en_US.UTF-8
+locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8
+EOF
+
+# So set these values manually in the config files.
+echo 'en_US.UTF-8 UTF-8' > /etc/locale.gen
+echo 'LANG=en_US.UTF-8' > /etc/locale.conf
+echo 'LANG=en_US.UTF-8' > /etc/default/locale
+
+echo 'dpkg-reconfigure changes'
+dpkg-reconfigure --frontend=noninteractive locales
+
+# create empty authorized_keys for integration test 'copy'
+[ -d /root/.ssh ] || mkdir /root/.ssh/
+
+touch /root/.ssh/authorized_keys
+
+# allow pip to install system packages for the tests
+rm -f /usr/lib/python3*/EXTERNALLY-MANAGED
diff -Nru ansible-core-2.14.16/lib/ansible/executor/task_executor.py ansible-core-2.14.18/lib/ansible/executor/task_executor.py
--- ansible-core-2.14.16/lib/ansible/executor/task_executor.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible/executor/task_executor.py 2024-11-04 19:35:24.000000000 +0100
@@ -645,8 +645,8 @@
self._handler.cleanup()
display.debug("handler run complete")
- # preserve no log
- result["_ansible_no_log"] = no_log
+ # propagate no log to result- the action can set this, so only overwrite it with the task's value if missing or falsey
+ result["_ansible_no_log"] = bool(no_log or result.get('_ansible_no_log', False))
if self._task.action not in C._ACTION_WITH_CLEAN_FACTS:
result = wrap_var(result)
diff -Nru ansible-core-2.14.16/lib/ansible/galaxy/role.py ansible-core-2.14.18/lib/ansible/galaxy/role.py
--- ansible-core-2.14.16/lib/ansible/galaxy/role.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible/galaxy/role.py 2024-11-04 19:35:24.000000000 +0100
@@ -387,6 +387,8 @@
else:
os.makedirs(self.path)
+ resolved_archive = unfrackpath(archive_parent_dir, follow=False)
+
# We strip off any higher-level directories for all of the files
# contained within the tar file here. The default is 'github_repo-target'.
# Gerrit instances, on the other hand, does not have a parent directory at all.
@@ -401,33 +403,29 @@
if not (attr_value := getattr(member, attr, None)):
continue
- if attr_value.startswith(os.sep) and not is_subpath(attr_value, archive_parent_dir):
- err = f"Invalid {attr} for tarfile member: path {attr_value} is not a subpath of the role {archive_parent_dir}"
- raise AnsibleError(err)
-
if attr == 'linkname':
# Symlinks are relative to the link
- relative_to_archive_dir = os.path.dirname(getattr(member, 'name', ''))
- archive_dir_path = os.path.join(archive_parent_dir, relative_to_archive_dir, attr_value)
+ relative_to = os.path.dirname(getattr(member, 'name', ''))
else:
# Normalize paths that start with the archive dir
attr_value = attr_value.replace(archive_parent_dir, "", 1)
attr_value = os.path.join(*attr_value.split(os.sep)) # remove leading os.sep
- archive_dir_path = os.path.join(archive_parent_dir, attr_value)
+ relative_to = ''
- resolved_archive = unfrackpath(archive_parent_dir)
- resolved_path = unfrackpath(archive_dir_path)
- if not is_subpath(resolved_path, resolved_archive):
- err = f"Invalid {attr} for tarfile member: path {resolved_path} is not a subpath of the role {resolved_archive}"
+ full_path = os.path.join(resolved_archive, relative_to, attr_value)
+ if not is_subpath(full_path, resolved_archive, real=True):
+ err = f"Invalid {attr} for tarfile member: path {full_path} is not a subpath of the role {resolved_archive}"
raise AnsibleError(err)
- relative_path = os.path.join(*resolved_path.replace(resolved_archive, "", 1).split(os.sep)) or '.'
+ relative_path_dir = os.path.join(resolved_archive, relative_to)
+ relative_path = os.path.join(*full_path.replace(relative_path_dir, "", 1).split(os.sep))
setattr(member, attr, relative_path)
if _check_working_data_filter():
# deprecated: description='extract fallback without filter' python_version='3.11'
role_tar_file.extract(member, to_native(self.path), filter='data') # type: ignore[call-arg]
else:
+ # Remove along with manual path filter once Python 3.12 is minimum supported version
role_tar_file.extract(member, to_native(self.path))
# write out the install info file for later use
diff -Nru ansible-core-2.14.16/lib/ansible/modules/user.py ansible-core-2.14.18/lib/ansible/modules/user.py
--- ansible-core-2.14.16/lib/ansible/modules/user.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible/modules/user.py 2024-11-04 19:35:24.000000000 +0100
@@ -1152,9 +1152,11 @@
overwrite = None
try:
ssh_key_file = self.get_ssh_key_path()
+ pub_file = '%s.pub' % ssh_key_file
except Exception as e:
return (1, '', to_native(e))
ssh_dir = os.path.dirname(ssh_key_file)
+
if not os.path.exists(ssh_dir):
if self.module.check_mode:
return (0, '', '')
@@ -1163,12 +1165,23 @@
os.chown(ssh_dir, info[2], info[3])
except OSError as e:
return (1, '', 'Failed to create %s: %s' % (ssh_dir, to_native(e)))
+
if os.path.exists(ssh_key_file):
if self.force:
- # ssh-keygen doesn't support overwriting the key interactively, so send 'y' to confirm
+ self.module.warn('Overwriting existing ssh key private file "%s"' % ssh_key_file)
overwrite = 'y'
else:
+ self.module.warn('Found existing ssh key private file "%s", no force, so skipping ssh-keygen generation' % ssh_key_file)
return (None, 'Key already exists, use "force: yes" to overwrite', '')
+
+ if os.path.exists(pub_file):
+ if self.force:
+ self.module.warn('Overwriting existing ssh key public file "%s"' % pub_file)
+ os.unlink(pub_file)
+ else:
+ self.module.warn('Found existing ssh key public file "%s", no force, so skipping ssh-keygen generation' % pub_file)
+ return (None, 'Public key already exists, use "force: yes" to overwrite', '')
+
cmd = [self.module.get_bin_path('ssh-keygen', True)]
cmd.append('-t')
cmd.append(self.ssh_type)
@@ -1235,7 +1248,7 @@
# If the keys were successfully created, we should be able
# to tweak ownership.
os.chown(ssh_key_file, info[2], info[3])
- os.chown('%s.pub' % ssh_key_file, info[2], info[3])
+ os.chown(pub_file, info[2], info[3])
return (rc, out, err)
def ssh_key_fingerprint(self):
diff -Nru ansible-core-2.14.16/lib/ansible/module_utils/ansible_release.py ansible-core-2.14.18/lib/ansible/module_utils/ansible_release.py
--- ansible-core-2.14.16/lib/ansible/module_utils/ansible_release.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible/module_utils/ansible_release.py 2024-11-04 19:35:24.000000000 +0100
@@ -19,6 +19,6 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-__version__ = '2.14.16'
+__version__ = '2.14.18'
__author__ = 'Ansible, Inc.'
__codename__ = "C'mon Everybody"
diff -Nru ansible-core-2.14.16/lib/ansible/plugins/action/include_vars.py ansible-core-2.14.18/lib/ansible/plugins/action/include_vars.py
--- ansible-core-2.14.16/lib/ansible/plugins/action/include_vars.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible/plugins/action/include_vars.py 2024-11-04 19:35:24.000000000 +0100
@@ -237,7 +237,8 @@
b_data, show_content = self._loader._get_file_contents(filename)
data = to_text(b_data, errors='surrogate_or_strict')
- self.show_content = show_content
+ self.show_content &= show_content # mask all results if any file was encrypted
+
data = self._loader.load(data, file_name=filename, show_content=show_content)
if not data:
data = dict()
diff -Nru ansible-core-2.14.16/lib/ansible/release.py ansible-core-2.14.18/lib/ansible/release.py
--- ansible-core-2.14.16/lib/ansible/release.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible/release.py 2024-11-04 19:35:24.000000000 +0100
@@ -19,6 +19,6 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
-__version__ = '2.14.16'
+__version__ = '2.14.18'
__author__ = 'Ansible, Inc.'
__codename__ = "C'mon Everybody"
diff -Nru ansible-core-2.14.16/lib/ansible_core.egg-info/PKG-INFO ansible-core-2.14.18/lib/ansible_core.egg-info/PKG-INFO
--- ansible-core-2.14.16/lib/ansible_core.egg-info/PKG-INFO 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible_core.egg-info/PKG-INFO 2024-11-04 19:35:24.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: ansible-core
-Version: 2.14.16
+Version: 2.14.18
Summary: Radically simple IT automation
Home-page: https://ansible.com/
Author: Ansible, Inc.
diff -Nru ansible-core-2.14.16/lib/ansible_core.egg-info/SOURCES.txt ansible-core-2.14.18/lib/ansible_core.egg-info/SOURCES.txt
--- ansible-core-2.14.16/lib/ansible_core.egg-info/SOURCES.txt 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/lib/ansible_core.egg-info/SOURCES.txt 2024-11-04 19:35:24.000000000 +0100
@@ -875,6 +875,11 @@
test/integration/targets/ansible-galaxy-collection/vars/main.yml
test/integration/targets/ansible-galaxy-role/aliases
test/integration/targets/ansible-galaxy-role/files/create-role-archive.py
+test/integration/targets/ansible-galaxy-role/files/safe-symlinks/defaults/main.yml
+test/integration/targets/ansible-galaxy-role/files/safe-symlinks/defaults/common_vars/subdir/group0/main.yml
+test/integration/targets/ansible-galaxy-role/files/safe-symlinks/handlers/utils.yml
+test/integration/targets/ansible-galaxy-role/files/safe-symlinks/meta/main.yml
+test/integration/targets/ansible-galaxy-role/files/safe-symlinks/tasks/utils/suite.yml
test/integration/targets/ansible-galaxy-role/meta/main.yml
test/integration/targets/ansible-galaxy-role/tasks/dir-traversal.yml
test/integration/targets/ansible-galaxy-role/tasks/main.yml
@@ -1716,6 +1721,7 @@
test/integration/targets/dict_transformations/tasks/test_convert_camelCase.yml
test/integration/targets/dict_transformations/tasks/test_convert_snake_case.yml
test/integration/targets/dnf/aliases
+test/integration/targets/dnf/filter_plugins/dnf_module_list.py
test/integration/targets/dnf/meta/main.yml
test/integration/targets/dnf/tasks/cacheonly.yml
test/integration/targets/dnf/tasks/dnf.yml
@@ -1730,10 +1736,6 @@
test/integration/targets/dnf/tasks/repo.yml
test/integration/targets/dnf/tasks/skip_broken_and_nobest.yml
test/integration/targets/dnf/tasks/test_sos_removal.yml
-test/integration/targets/dnf/vars/CentOS.yml
-test/integration/targets/dnf/vars/Fedora.yml
-test/integration/targets/dnf/vars/RedHat-9.yml
-test/integration/targets/dnf/vars/RedHat.yml
test/integration/targets/dnf/vars/main.yml
test/integration/targets/dpkg_selections/aliases
test/integration/targets/dpkg_selections/defaults/main.yaml
@@ -2058,37 +2060,6 @@
test/integration/targets/incidental_ios_file/tasks/main.yaml
test/integration/targets/incidental_ios_file/tests/cli/net_get.yaml
test/integration/targets/incidental_ios_file/tests/cli/net_put.yaml
-test/integration/targets/incidental_vyos_config/aliases
-test/integration/targets/incidental_vyos_config/defaults/main.yaml
-test/integration/targets/incidental_vyos_config/tasks/cli.yaml
-test/integration/targets/incidental_vyos_config/tasks/cli_config.yaml
-test/integration/targets/incidental_vyos_config/tasks/main.yaml
-test/integration/targets/incidental_vyos_config/tests/cli/backup.yaml
-test/integration/targets/incidental_vyos_config/tests/cli/check_config.yaml
-test/integration/targets/incidental_vyos_config/tests/cli/comment.yaml
-test/integration/targets/incidental_vyos_config/tests/cli/config.cfg
-test/integration/targets/incidental_vyos_config/tests/cli/save.yaml
-test/integration/targets/incidental_vyos_config/tests/cli/simple.yaml
-test/integration/targets/incidental_vyos_config/tests/cli_config/cli_backup.yaml
-test/integration/targets/incidental_vyos_config/tests/cli_config/cli_basic.yaml
-test/integration/targets/incidental_vyos_config/tests/cli_config/cli_comment.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/aliases
-test/integration/targets/incidental_vyos_lldp_interfaces/defaults/main.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/meta/main.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tasks/cli.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tasks/main.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate_intf.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_remove_config.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/deleted.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/empty_config.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/merged.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/overridden.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/replaced.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/rtt.yaml
-test/integration/targets/incidental_vyos_lldp_interfaces/vars/main.yaml
-test/integration/targets/incidental_vyos_prepare_tests/aliases
-test/integration/targets/incidental_vyos_prepare_tests/tasks/main.yaml
test/integration/targets/incidental_win_reboot/aliases
test/integration/targets/incidental_win_reboot/tasks/main.yml
test/integration/targets/incidental_win_reboot/templates/post_reboot.ps1
@@ -2277,6 +2248,8 @@
test/integration/targets/include_vars/aliases
test/integration/targets/include_vars-ad-hoc/aliases
test/integration/targets/include_vars-ad-hoc/runme.sh
+test/integration/targets/include_vars-ad-hoc/vaultpass
+test/integration/targets/include_vars-ad-hoc/dir/encrypted.yml
test/integration/targets/include_vars-ad-hoc/dir/inc.yml
test/integration/targets/include_vars/defaults/main.yml
test/integration/targets/include_vars/tasks/main.yml
@@ -2835,18 +2808,16 @@
test/integration/targets/module_utils_urls/library/test_peercert.py
test/integration/targets/module_utils_urls/meta/main.yml
test/integration/targets/module_utils_urls/tasks/main.yml
-test/integration/targets/network_cli/aliases
-test/integration/targets/network_cli/passworded_user.yml
-test/integration/targets/network_cli/runme.sh
-test/integration/targets/network_cli/setup.yml
-test/integration/targets/network_cli/teardown.yml
test/integration/targets/no_log/aliases
+test/integration/targets/no_log/ansible_no_log_in_result.yml
test/integration/targets/no_log/dynamic.yml
test/integration/targets/no_log/no_log_config.yml
test/integration/targets/no_log/no_log_local.yml
test/integration/targets/no_log/no_log_suboptions.yml
test/integration/targets/no_log/no_log_suboptions_invalid.yml
test/integration/targets/no_log/runme.sh
+test/integration/targets/no_log/secretvars.yml
+test/integration/targets/no_log/action_plugins/action_sets_no_log.py
test/integration/targets/no_log/library/module.py
test/integration/targets/noexec/aliases
test/integration/targets/noexec/inventory
@@ -3588,6 +3559,7 @@
test/integration/targets/user/files/userlist.sh
test/integration/targets/user/meta/main.yml
test/integration/targets/user/tasks/main.yml
+test/integration/targets/user/tasks/ssh_keygen.yml
test/integration/targets/user/tasks/test_create_system_user.yml
test/integration/targets/user/tasks/test_create_user.yml
test/integration/targets/user/tasks/test_create_user_home.yml
@@ -4155,34 +4127,6 @@
test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_command.py
test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_config.py
test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/terminal/ios.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/action/vyos.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/cliconf/vyos.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/facts/facts.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/l3_interfaces/l3_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/static_routes/static_routes.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/facts.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/legacy/base.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/utils/utils.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_lldp_interfaces.py
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/terminal/vyos.py
test/support/windows-integration/collections/ansible_collections/ansible/windows/plugins/action/win_copy.py
test/support/windows-integration/collections/ansible_collections/ansible/windows/plugins/module_utils/WebRequest.psm1
test/support/windows-integration/collections/ansible_collections/ansible/windows/plugins/modules/async_status.ps1
diff -Nru ansible-core-2.14.16/packaging/release.py ansible-core-2.14.18/packaging/release.py
--- ansible-core-2.14.16/packaging/release.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/packaging/release.py 2024-11-04 19:35:24.000000000 +0100
@@ -369,6 +369,7 @@
ANSIBLE_BIN_DIR = CHECKOUT_DIR / "bin"
ANSIBLE_RELEASE_FILE = ANSIBLE_DIR / "release.py"
ANSIBLE_REQUIREMENTS_FILE = CHECKOUT_DIR / "requirements.txt"
+ANSIBLE_PYPROJECT_TOML_FILE = CHECKOUT_DIR / "pyproject.toml"
DIST_DIR = CHECKOUT_DIR / "dist"
VENV_DIR = DIST_DIR / ".venv" / "release"
@@ -708,6 +709,35 @@
return env
+def get_pypi_project(repository: str, project: str, version: Version | None = None) -> dict[str, t.Any]:
+ """Return the project JSON from PyPI for the specified repository, project and version (optional)."""
+ endpoint = PYPI_ENDPOINTS[repository]
+
+ if version:
+ url = f"{endpoint}/{project}/{version}/json"
+ else:
+ url = f"{endpoint}/{project}/json"
+
+ opener = urllib.request.build_opener()
+ response: http.client.HTTPResponse
+
+ try:
+ with opener.open(url) as response:
+ data = json.load(response)
+ except urllib.error.HTTPError as ex:
+ if version:
+ target = f'{project!r} version {version}'
+ else:
+ target = f'{project!r}'
+
+ if ex.status == http.HTTPStatus.NOT_FOUND:
+ raise ApplicationError(f"Could not find {target} on PyPI.") from None
+
+ raise RuntimeError(f"Failed to get {target} from PyPI.") from ex
+
+ return data
+
+
def get_ansible_version(version: str | None = None, /, commit: str | None = None, mode: VersionMode = VersionMode.DEFAULT) -> Version:
"""Parse and return the current ansible-core version, the provided version or the version from the provided commit."""
if version and commit:
@@ -751,12 +781,17 @@
pre = ""
elif not pre and version.pre is not None:
pre = f"{version.pre[0]}{version.pre[1]}"
+ elif not pre:
+ pre = "b1" # when there is no existing pre and none specified, advance to b1
+
elif version.is_postrelease:
# The next version of a post release is the next pre-release *or* micro release component.
if final:
pre = ""
elif not pre and version.pre is not None:
pre = f"{version.pre[0]}{version.pre[1] + 1}"
+ elif not pre:
+ pre = "rc1" # when there is no existing pre and none specified, advance to rc1
if version.pre is None:
micro = version.micro + 1
@@ -797,6 +832,38 @@
ANSIBLE_RELEASE_FILE.write_text(updated)
+def get_latest_setuptools_version() -> Version:
+ """Return the latest setuptools version found on PyPI."""
+ data = get_pypi_project('pypi', 'setuptools')
+ version = Version(data['info']['version'])
+
+ return version
+
+
+def set_setuptools_upper_bound(requested_version: Version) -> None:
+ """Set the upper bound on setuptools in pyproject.toml."""
+ current = ANSIBLE_PYPROJECT_TOML_FILE.read_text()
+ pattern = re.compile(r'^(?P<begin>requires = \["setuptools >= )(?P<lower>[^,]+)(?P<middle>, <= )(?P<upper>[^"]+)(?P<end>".*)$', re.MULTILINE)
+ match = pattern.search(current)
+
+ if not match:
+ raise ApplicationError(f"Unable to find the 'requires' entry in: {ANSIBLE_PYPROJECT_TOML_FILE.relative_to(CHECKOUT_DIR)}")
+
+ current_version = Version(match.group('upper'))
+
+ if requested_version == current_version:
+ return
+
+ display.show(f"Updating setuptools upper bound from {current_version} to {requested_version} ...")
+
+ updated = pattern.sub(fr'\g<begin>\g<lower>\g<middle>{requested_version}\g<end>', current)
+
+ if current == updated:
+ raise RuntimeError("Failed to set the setuptools upper bound.")
+
+ ANSIBLE_PYPROJECT_TOML_FILE.write_text(updated)
+
+
def create_reproducible_sdist(original_path: pathlib.Path, output_path: pathlib.Path, mtime: int) -> None:
"""Read the specified sdist and write out a new copy with uniform file metadata at the specified location."""
with tarfile.open(original_path) as original_archive:
@@ -873,21 +940,7 @@
@functools.cache
def get_release_artifact_details(repository: str, version: Version, validate: bool) -> list[ReleaseArtifact]:
"""Return information about the release artifacts hosted on PyPI."""
- endpoint = PYPI_ENDPOINTS[repository]
- url = f"{endpoint}/ansible-core/{version}/json"
-
- opener = urllib.request.build_opener()
- response: http.client.HTTPResponse
-
- try:
- with opener.open(url) as response:
- data = json.load(response)
- except urllib.error.HTTPError as ex:
- if ex.status == http.HTTPStatus.NOT_FOUND:
- raise ApplicationError(f"Version {version} not found on PyPI.") from None
-
- raise RuntimeError(f"Failed to get {version} from PyPI: {ex}") from ex
-
+ data = get_pypi_project(repository, 'ansible-core', version)
artifacts = [describe_release_artifact(version, item, validate) for item in data["urls"]]
expected_artifact_types = {"bdist_wheel", "sdist"}
@@ -1041,7 +1094,7 @@
# Release Artifacts
{%- for release in releases %}
-* {{ release.package_label }}: [{{ release.url|basename }}]({{ release.url }}) - {{ release.size }} bytes
+* {{ release.package_label }}: [{{ release.url|basename }}]({{ release.url }}) - ‌{{ release.size }} bytes
* {{ release.digest }} ({{ release.digest_algorithm }})
{%- endfor %}
"""
@@ -1130,9 +1183,10 @@
pre=dict(exclusive="version", help="increment version to the specified pre-release (aN, bN, rcN)"),
final=dict(exclusive="version", action="store_true", help="increment version to the next final release"),
commit=dict(help="commit to tag"),
- mailto=dict(name="--no-mailto", action="store_false", help="write announcement to console instead of using a mailto: link"),
+ mailto=dict(name="--mailto", action="store_true", help="write announcement to mailto link instead of console"),
validate=dict(name="--no-validate", action="store_false", help="disable validation of PyPI artifacts against local ones"),
prompt=dict(name="--no-prompt", action="store_false", help="disable interactive prompt before publishing with twine"),
+ setuptools=dict(name='--no-setuptools', action="store_false", help="disable updating setuptools upper bound"),
allow_tag=dict(action="store_true", help="allow an existing release tag (for testing)"),
allow_stale=dict(action="store_true", help="allow a stale checkout (for testing)"),
allow_dirty=dict(action="store_true", help="allow untracked files and files with changes (for testing)"),
@@ -1189,10 +1243,11 @@
# noinspection PyUnusedLocal
@command
-def prepare(final: bool = False, pre: str | None = None, version: str | None = None) -> None:
+def prepare(final: bool = False, pre: str | None = None, version: str | None = None, setuptools: bool | None = None) -> None:
"""Prepare a release."""
command.run(
update_version,
+ update_setuptools,
check_state,
generate_summary,
generate_changelog,
@@ -1214,6 +1269,16 @@
@command
+def update_setuptools(setuptools: bool) -> None:
+ """Update the setuptools upper bound in pyproject.toml."""
+ if not setuptools:
+ return
+
+ requested_version = get_latest_setuptools_version()
+ set_setuptools_upper_bound(requested_version)
+
+
+@command
def generate_summary() -> None:
"""Generate a summary changelog fragment for this release."""
version = get_ansible_version()
@@ -1259,6 +1324,7 @@
add=(
CHANGELOGS_DIR,
ANSIBLE_RELEASE_FILE,
+ ANSIBLE_PYPROJECT_TOML_FILE,
),
allow_stale=allow_stale,
)
diff -Nru ansible-core-2.14.16/PKG-INFO ansible-core-2.14.18/PKG-INFO
--- ansible-core-2.14.16/PKG-INFO 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/PKG-INFO 2024-11-04 19:35:24.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: ansible-core
-Version: 2.14.16
+Version: 2.14.18
Summary: Radically simple IT automation
Home-page: https://ansible.com/
Author: Ansible, Inc.
diff -Nru ansible-core-2.14.16/pyproject.toml ansible-core-2.14.18/pyproject.toml
--- ansible-core-2.14.16/pyproject.toml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/pyproject.toml 2024-11-04 19:35:24.000000000 +0100
@@ -1,3 +1,3 @@
[build-system]
-requires = ["setuptools >= 45.2.0"]
+requires = ["setuptools >= 45.2.0, <= 75.3.0"] # lower bound to support controller Python versions, upper bound for latest version tested at release
build-backend = "setuptools.build_meta"
diff -Nru ansible-core-2.14.16/test/integration/targets/ansible-galaxy-role/tasks/valid-role-symlinks.yml ansible-core-2.14.18/test/integration/targets/ansible-galaxy-role/tasks/valid-role-symlinks.yml
--- ansible-core-2.14.16/test/integration/targets/ansible-galaxy-role/tasks/valid-role-symlinks.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/ansible-galaxy-role/tasks/valid-role-symlinks.yml 2024-11-04 19:35:24.000000000 +0100
@@ -1,78 +1,38 @@
-- name: create test directories
- file:
- path: '{{ remote_tmp_dir }}/dir-traversal/{{ item }}'
- state: directory
- loop:
- - source
- - target
- - roles
-
-- name: create subdir in the role content to test relative symlinks
- file:
- dest: '{{ remote_tmp_dir }}/dir-traversal/source/role_subdir'
- state: directory
-
-- copy:
- dest: '{{ remote_tmp_dir }}/dir-traversal/source/role_subdir/.keep'
- content: ''
-
-- set_fact:
- installed_roles: "{{ remote_tmp_dir | realpath }}/dir-traversal/roles"
-
-- name: build role with symlink to a directory in the role
- script:
- chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
- cmd: create-role-archive.py safe-link-dir.tar ./ role_subdir/..
- executable: '{{ ansible_playbook_python }}'
-
-- name: install role successfully
- command:
- cmd: 'ansible-galaxy role install --roles-path {{ remote_tmp_dir }}/dir-traversal/roles safe-link-dir.tar'
- chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
- register: galaxy_install_ok
-
-- name: check for the directory symlink in the role
- stat:
- path: "{{ installed_roles }}/safe-link-dir.tar/symlink"
- register: symlink_in_role
-
-- assert:
- that:
- - symlink_in_role.stat.exists
- - symlink_in_role.stat.lnk_source == installed_roles + '/safe-link-dir.tar'
-
-- name: remove tarfile for next test
- file:
- path: '{{ remote_tmp_dir }}/dir-traversal/source/safe-link-dir.tar'
- state: absent
-
-- name: build role with safe relative symlink
- script:
- chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
- cmd: create-role-archive.py safe.tar ./ role_subdir/../context.txt
- executable: '{{ ansible_playbook_python }}'
-
-- name: install role successfully
- command:
- cmd: 'ansible-galaxy role install --roles-path {{ remote_tmp_dir }}/dir-traversal/roles safe.tar'
- chdir: '{{ remote_tmp_dir }}/dir-traversal/source'
- register: galaxy_install_ok
-
-- name: check for symlink in role
- stat:
- path: "{{ installed_roles }}/safe.tar/symlink"
- register: symlink_in_role
-
-- assert:
- that:
- - symlink_in_role.stat.exists
- - symlink_in_role.stat.lnk_source == installed_roles + '/safe.tar/context.txt'
-
-- name: remove test directories
- file:
- path: '{{ remote_tmp_dir }}/dir-traversal/{{ item }}'
- state: absent
- loop:
- - source
- - target
- - roles
+- delegate_to: localhost
+ block:
+ - name: Create archive
+ command: "tar -cf safe-symlinks.tar {{ role_path }}/files/safe-symlinks"
+ args:
+ chdir: "{{ remote_tmp_dir }}"
+
+ - name: Install role successfully
+ command: ansible-galaxy role install --roles-path '{{ remote_tmp_dir }}/roles' safe-symlinks.tar
+ args:
+ chdir: "{{ remote_tmp_dir }}"
+
+ - name: Validate each of the symlinks exists
+ stat:
+ path: "{{ remote_tmp_dir }}/roles/safe-symlinks.tar/{{ item }}"
+ loop:
+ - defaults/main.yml
+ - handlers/utils.yml
+ register: symlink_stat
+
+ - assert:
+ that:
+ - symlink_stat.results[0].stat.exists
+ - symlink_stat.results[0].stat.lnk_source == ((dest, 'roles/safe-symlinks.tar/defaults/common_vars/subdir/group0/main.yml') | path_join)
+ - symlink_stat.results[1].stat.exists
+ - symlink_stat.results[1].stat.lnk_source == ((dest, 'roles/safe-symlinks.tar/tasks/utils/suite.yml') | path_join)
+ vars:
+ dest: "{{ remote_tmp_dir | realpath }}"
+
+ always:
+ - name: Clean up
+ file:
+ path: "{{ item }}"
+ state: absent
+ delegate_to: localhost
+ loop:
+ - "{{ remote_tmp_dir }}/roles/"
+ - "{{ remote_tmp_dir }}/safe-symlinks.tar"
diff -Nru ansible-core-2.14.16/test/integration/targets/ansible-vault/runme.sh ansible-core-2.14.18/test/integration/targets/ansible-vault/runme.sh
--- ansible-core-2.14.16/test/integration/targets/ansible-vault/runme.sh 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/ansible-vault/runme.sh 2024-11-04 19:35:24.000000000 +0100
@@ -534,21 +534,22 @@
ansible-vault encrypt_string content
ansible-vault encrypt_string content --encrypt-vault-id id3
-set +e
-
# Try to use a missing vault password file
-ansible-vault encrypt_string content --encrypt-vault-id id1 2>&1 | tee out.txt
-test $? -ne 0
-grep out.txt -e '[WARNING]: Error getting vault password file (id1)'
-grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id2 in the known vault-ids ['id3']"
+if ansible-vault encrypt_string content --encrypt-vault-id id1 > out.txt 2>&1; then
+ echo "command did not fail"
+ exit 1
+fi
+grep out.txt -e '\[WARNING\]: Error getting vault password file (id1)'
+grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id1 in the known vault-ids \['id3'\]"
# Try to use an inaccessible vault password file
-ansible-vault encrypt_string content --encrypt-vault-id id2 2>&1 | tee out.txt
-test $? -ne 0
-grep out.txt -e "[WARNING]: Error in vault password file loading (id2)"
-grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id2 in the known vault-ids ['id3']"
+if ansible-vault encrypt_string content --encrypt-vault-id id2 > out.txt 2>&1; then
+ echo "command did not fail"
+ exit 1
+fi
+grep out.txt -e "\[WARNING\]: Error in vault password file loading (id2)"
+grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id2 in the known vault-ids \['id3'\]"
-set -e
unset ANSIBLE_VAULT_IDENTITY_LIST
# 'real script'
diff -Nru ansible-core-2.14.16/test/integration/targets/apt_repository/tasks/apt.yml ansible-core-2.14.18/test/integration/targets/apt_repository/tasks/apt.yml
--- ansible-core-2.14.16/test/integration/targets/apt_repository/tasks/apt.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/apt_repository/tasks/apt.yml 2024-11-04 19:35:24.000000000 +0100
@@ -62,7 +62,10 @@
- 'cache_before.stat.mtime != cache_after.stat.mtime'
- name: 'ensure ppa key is installed (expect: pass)'
- apt_key: id='{{test_ppa_key}}' state=present
+ apt_key:
+ id: '{{test_ppa_key}}'
+ state: present
+ keyserver: keyserver.ubuntu.com
#
# TEST: apt_repository: repo=<name> update_cache=no
@@ -93,7 +96,10 @@
- 'cache_before.stat.mtime == cache_after.stat.mtime'
- name: 'ensure ppa key is installed (expect: pass)'
- apt_key: id='{{test_ppa_key}}' state=present
+ apt_key:
+ id: '{{test_ppa_key}}'
+ state: present
+ keyserver: keyserver.ubuntu.com
#
# TEST: apt_repository: repo=<name> update_cache=yes
@@ -124,7 +130,10 @@
- 'cache_before.stat.mtime != cache_after.stat.mtime'
- name: 'ensure ppa key is installed (expect: pass)'
- apt_key: id='{{test_ppa_key}}' state=present
+ apt_key:
+ id: '{{test_ppa_key}}'
+ state: present
+ keyserver: keyserver.ubuntu.com
#
# TEST: apt_repository: repo=<spec>
@@ -136,7 +145,10 @@
register: cache_before
- name: ensure ppa key is present before adding repo that requires authentication
- apt_key: keyserver=keyserver.ubuntu.com id='{{test_ppa_key}}' state=present
+ apt_key:
+ id: '{{test_ppa_key}}'
+ state: present
+ keyserver: keyserver.ubuntu.com
- name: 'name=<spec> (expect: pass)'
apt_repository: repo='{{test_ppa_spec}}' state=present
@@ -181,7 +193,10 @@
register: cache_before
- name: ensure ppa key is present before adding repo that requires authentication
- apt_key: keyserver=keyserver.ubuntu.com id='{{test_ppa_key}}' state=present
+ apt_key:
+ id: '{{test_ppa_key}}'
+ state: present
+ keyserver: keyserver.ubuntu.com
- name: 'name=<spec> filename=<filename> (expect: pass)'
apt_repository: repo='{{test_ppa_spec}}' filename='{{test_ppa_filename}}' state=present
diff -Nru ansible-core-2.14.16/test/integration/targets/collections_runtime_pythonpath/ansible-collection-python-dist-boo/pyproject.toml ansible-core-2.14.18/test/integration/targets/collections_runtime_pythonpath/ansible-collection-python-dist-boo/pyproject.toml
--- ansible-core-2.14.16/test/integration/targets/collections_runtime_pythonpath/ansible-collection-python-dist-boo/pyproject.toml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/collections_runtime_pythonpath/ansible-collection-python-dist-boo/pyproject.toml 2024-11-04 19:35:24.000000000 +0100
@@ -1,6 +1,5 @@
[build-system]
requires = [
"setuptools >= 44",
- "wheel",
]
build-backend = "setuptools.build_meta"
diff -Nru ansible-core-2.14.16/test/integration/targets/collections_runtime_pythonpath/runme.sh ansible-core-2.14.18/test/integration/targets/collections_runtime_pythonpath/runme.sh
--- ansible-core-2.14.16/test/integration/targets/collections_runtime_pythonpath/runme.sh 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/collections_runtime_pythonpath/runme.sh 2024-11-04 19:35:24.000000000 +0100
@@ -25,11 +25,11 @@
=== Test that the module \
gets picked up if installed \
into site-packages ===
-python -m pip install pep517
-( # Build a binary Python dist (a wheel) using PEP517:
+python -m pip install build
+( # Build a binary Python dist (a wheel) using build:
cp -r ansible-collection-python-dist-boo "${OUTPUT_DIR}/"
cd "${OUTPUT_DIR}/ansible-collection-python-dist-boo"
- python -m pep517.build --binary --out-dir dist .
+ python -m build -w -o dist .
)
# Install a pre-built dist with pip:
python -m pip install \
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/filter_plugins/dnf_module_list.py ansible-core-2.14.18/test/integration/targets/dnf/filter_plugins/dnf_module_list.py
--- ansible-core-2.14.16/test/integration/targets/dnf/filter_plugins/dnf_module_list.py 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/dnf/filter_plugins/dnf_module_list.py 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,40 @@
+# Copyright: Contributors to the Ansible project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import annotations
+
+from collections import Counter
+
+
+def parse_module_list(stdout):
+ lines = stdout.splitlines()
+ name_offset = 0
+ empty_offset = -1
+ modules = []
+ for i, line in enumerate(lines):
+ if line.startswith('Name '):
+ name_offset = i + 1
+ if not line.strip():
+ empty_offset = i
+ for line in lines[name_offset:empty_offset]:
+ cols = line.split()[:3]
+ modules.append({
+ 'name': cols[0],
+ 'version': cols[1],
+ 'profile': cols[2].rstrip(','), # Just the first profile
+ })
+ return modules
+
+
+def get_first_single_version_module(stdout):
+ modules = parse_module_list(stdout)
+ name = Counter([m['name'] for m in modules]).most_common()[-1][0]
+ module, = [m for m in modules if m['name'] == name]
+ return module
+
+
+class FilterModule:
+ def filters(self):
+ return {
+ 'get_first_single_version_module': get_first_single_version_module,
+ }
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/tasks/main.yml ansible-core-2.14.18/test/integration/targets/dnf/tasks/main.yml
--- ansible-core-2.14.16/test/integration/targets/dnf/tasks/main.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/dnf/tasks/main.yml 2024-11-04 19:35:24.000000000 +0100
@@ -57,12 +57,30 @@
- ansible_distribution == 'Fedora'
- ansible_distribution_major_version is version('23', '>=')
-- include_tasks: modularity.yml
- when:
+- when:
- (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('29', '>=')) or
(ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))
- tags:
- - dnf_modularity
+ - not dnf5|default(false)
+ block:
+ # FUTURE - look at including AppStream support in our local repo
+ - name: list modules
+ command: dnf module list -q
+ register: module_list
+
+ # A module that only has a single version
+ - name: Find a module that meets our testing needs
+ set_fact:
+ astream_name: '@{{ module.name }}:{{ module.version }}/{{ module.profile }}'
+ astream_name_no_stream: '@{{ module.name }}/{{ module.profile }}'
+ vars:
+ module: '{{ module_list.stdout|get_first_single_version_module }}'
+
+ - include_tasks: modularity.yml
+ tags:
+ - dnf_modularity
+ rescue:
+ # Just in case something crazy happens when listing or parsing modules
+ - meta: noop
- include_tasks: logging.yml
when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('31', '>=')) or
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/tasks/modularity.yml ansible-core-2.14.18/test/integration/targets/dnf/tasks/modularity.yml
--- ansible-core-2.14.16/test/integration/targets/dnf/tasks/modularity.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/dnf/tasks/modularity.yml 2024-11-04 19:35:24.000000000 +0100
@@ -1,12 +1,3 @@
-# FUTURE - look at including AppStream support in our local repo
-- name: Include distribution specific variables
- include_vars: "{{ item }}"
- with_first_found:
- - files:
- - "{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_major_version }}.yml"
- - "{{ ansible_facts.distribution }}.yml"
- paths: ../vars
-
- name: install "{{ astream_name }}" module
dnf:
name: "{{ astream_name }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/vars/CentOS.yml ansible-core-2.14.18/test/integration/targets/dnf/vars/CentOS.yml
--- ansible-core-2.14.16/test/integration/targets/dnf/vars/CentOS.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/dnf/vars/CentOS.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-astream_name: '@php:7.2/minimal'
-astream_name_no_stream: '@php/minimal'
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/vars/Fedora.yml ansible-core-2.14.18/test/integration/targets/dnf/vars/Fedora.yml
--- ansible-core-2.14.16/test/integration/targets/dnf/vars/Fedora.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/dnf/vars/Fedora.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-astream_name: '@varnish:6.0/default'
-
-# For this to work, it needs to be that only shows once in `dnf module list`.
-# Such packages, that exist on all the versions we test on, are hard to come by.
-# TODO: This would be solved by using our own repo with modularity/streams.
-astream_name_no_stream: '@varnish/default'
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/vars/RedHat-9.yml ansible-core-2.14.18/test/integration/targets/dnf/vars/RedHat-9.yml
--- ansible-core-2.14.16/test/integration/targets/dnf/vars/RedHat-9.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/dnf/vars/RedHat-9.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-astream_name: '@php:8.1/minimal'
-astream_name_no_stream: '@php/minimal'
diff -Nru ansible-core-2.14.16/test/integration/targets/dnf/vars/RedHat.yml ansible-core-2.14.18/test/integration/targets/dnf/vars/RedHat.yml
--- ansible-core-2.14.16/test/integration/targets/dnf/vars/RedHat.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/dnf/vars/RedHat.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-astream_name: '@php:7.2/minimal'
-astream_name_no_stream: '@php/minimal'
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/aliases ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/aliases
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/aliases 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/aliases 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-shippable/vyos/incidental
-network/vyos
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/defaults/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/defaults/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/defaults/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/defaults/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
----
-testcase: "*"
-test_items: []
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tasks/cli_config.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tasks/cli_config.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tasks/cli_config.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tasks/cli_config.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,18 +0,0 @@
----
-- name: collect all cli_config test cases
- find:
- paths: "{{ role_path }}/tests/cli_config"
- patterns: "{{ testcase }}.yaml"
- register: test_cases
- delegate_to: localhost
-
-- name: set test_items
- set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
-
-- name: run test case (connection=ansible.netcommon.network_cli)
- include_tasks: "file={{ test_case_to_run }}"
- vars:
- ansible_connection: ansible.netcommon.network_cli
- with_items: "{{ test_items }}"
- loop_control:
- loop_var: test_case_to_run
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tasks/cli.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tasks/cli.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tasks/cli.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tasks/cli.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,26 +0,0 @@
----
-- name: collect all cli test cases
- find:
- paths: "{{ role_path }}/tests/cli"
- patterns: "{{ testcase }}.yaml"
- register: test_cases
- delegate_to: localhost
-
-- name: set test_items
- set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
-
-- name: run test case (connection=ansible.netcommon.network_cli)
- include_tasks: "file={{ test_case_to_run }}"
- vars:
- ansible_connection: ansible.netcommon.network_cli
- with_items: "{{ test_items }}"
- loop_control:
- loop_var: test_case_to_run
-
-- name: run test case (connection=local)
- include_tasks: "file={{ test_case_to_run }}"
- vars:
- ansible_connection: local
- with_first_found: "{{ test_items }}"
- loop_control:
- loop_var: test_case_to_run
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tasks/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tasks/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tasks/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tasks/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
----
-- {import_tasks: cli.yaml, tags: ['cli']}
-- {import_tasks: cli_config.yaml, tags: ['cli_config']}
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/backup.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/backup.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/backup.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/backup.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,113 +0,0 @@
----
-- debug: msg="START vyos/backup.yaml on connection={{ ansible_connection }}"
-
-- name: collect any backup files
- find:
- paths: "{{ role_path }}/backup"
- pattern: "{{ inventory_hostname_short }}_config*"
- register: backup_files
- connection: local
-
-- name: delete backup files
- file:
- path: "{{ item.path }}"
- state: absent
- with_items: "{{backup_files.files|default([])}}"
-
-- name: take configure backup
- vyos.vyos.vyos_config:
- backup: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: collect any backup files
- find:
- paths: "{{ role_path }}/backup"
- pattern: "{{ inventory_hostname_short }}_config*"
- register: backup_files
- connection: local
-
-- assert:
- that:
- - "backup_files.files is defined"
-
-- name: delete configurable backup file path
- file:
- path: "{{ item }}"
- state: absent
- with_items:
- - "{{ role_path }}/backup_test_dir/"
- - "{{ role_path }}/backup/backup.cfg"
-
-- name: take configuration backup in custom filename and directory path
- vyos.vyos.vyos_config:
- backup: true
- backup_options:
- filename: backup.cfg
- dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}"
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check if the backup file-1 exist
- find:
- paths: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}/backup.cfg"
- register: backup_file
- connection: local
-
-- assert:
- that:
- - "backup_file.files is defined"
-
-- name: take configuration backup in custom filename
- vyos.vyos.vyos_config:
- backup: true
- backup_options:
- filename: backup.cfg
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check if the backup file-2 exist
- find:
- paths: "{{ role_path }}/backup/backup.cfg"
- register: backup_file
- connection: local
-
-- assert:
- that:
- - "backup_file.files is defined"
-
-- name: take configuration backup in custom path and default filename
- vyos.vyos.vyos_config:
- backup: true
- backup_options:
- dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}"
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check if the backup file-3 exist
- find:
- paths: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}"
- pattern: "{{ inventory_hostname_short }}_config*"
- register: backup_file
- connection: local
-
-- assert:
- that:
- - "backup_file.files is defined"
-
-- debug: msg="END vyos/backup.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/check_config.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/check_config.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/check_config.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/check_config.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
----
-- debug: msg="START cli/config_check.yaml on connection={{ ansible_connection }}"
-
-- name: setup- ensure interface is not present
- vyos.vyos.vyos_config:
- lines: delete interfaces loopback lo
-
-- name: setup- create interface
- vyos.vyos.vyos_config:
- lines:
- - interfaces
- - interfaces loopback lo
- - interfaces loopback lo description test
- register: result
-
-# note collapsing the duplicate lines doesn't work if
-# lines:
-# - interfaces loopback lo description test
-# - interfaces loopback lo
-# - interfaces
-
-- name: Check that multiple duplicate lines collapse into a single commands
- assert:
- that:
- - "result.commands|length == 1"
-
-- name: Check that set is correctly prepended
- assert:
- that:
- - "result.commands[0] == 'set interfaces loopback lo description test'"
-
-- name: configure config_check config command
- vyos.vyos.vyos_config:
- lines: delete interfaces loopback lo
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check config_check config command idempontent
- vyos.vyos.vyos_config:
- lines: delete interfaces loopback lo
- register: result
-
-- assert:
- that:
- - "result.changed == false"
-
-- name: check multiple line config filter is working
- vyos.vyos.vyos_config:
- lines:
- - set system login user esa level admin
- - set system login user esa authentication encrypted-password '!abc!'
- - set system login user vyos level admin
- - set system login user vyos authentication encrypted-password 'abc'
- register: result
-
-- assert:
- that:
- - "result.filtered|length == 2"
-
-- debug: msg="END cli/config_check.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/comment.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/comment.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/comment.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/comment.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,34 +0,0 @@
----
-- debug: msg="START cli/comment.yaml on connection={{ ansible_connection }}"
-
-- name: setup
- vyos.vyos.vyos_config:
- lines: set system host-name {{ inventory_hostname_short }}
- match: none
-
-- name: configure using comment
- vyos.vyos.vyos_config:
- lines: set system host-name foo
- comment: this is a test
- register: result
-
-- assert:
- that:
- - "result.changed == true"
- - "'set system host-name foo' in result.commands"
-
-- name: collect system commits
- vyos.vyos.vyos_command:
- commands: show system commit
- register: result
-
-- assert:
- that:
- - "'this is a test' in result.stdout_lines[0][1]"
-
-- name: teardown
- vyos.vyos.vyos_config:
- lines: set system host-name {{ inventory_hostname_short }}
- match: none
-
-- debug: msg="END cli/comment.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/config.cfg ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/config.cfg
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/config.cfg 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/config.cfg 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
- set service lldp
- set protocols static
-
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/save.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/save.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/save.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/save.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,54 +0,0 @@
----
-- debug: msg="START cli/save.yaml on connection={{ ansible_connection }}"
-
-- name: setup
- vyos.vyos.vyos_config:
- lines: set system host-name {{ inventory_hostname_short }}
- match: none
-
-- name: configure hostaname and save
- vyos.vyos.vyos_config:
- lines: set system host-name foo
- save: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
- - "'set system host-name foo' in result.commands"
-
-- name: configure hostaname and don't save
- vyos.vyos.vyos_config:
- lines: set system host-name bar
- register: result
-
-- assert:
- that:
- - "result.changed == true"
- - "'set system host-name bar' in result.commands"
-
-- name: save config
- vyos.vyos.vyos_config:
- save: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: save config again
- vyos.vyos.vyos_config:
- save: true
- register: result
-
-- assert:
- that:
- - "result.changed == false"
-
-- name: teardown
- vyos.vyos.vyos_config:
- lines: set system host-name {{ inventory_hostname_short }}
- match: none
- save: true
-
-- debug: msg="END cli/simple.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/simple.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/simple.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli/simple.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli/simple.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,53 +0,0 @@
----
-- debug: msg="START cli/simple.yaml on connection={{ ansible_connection }}"
-
-- name: setup
- vyos.vyos.vyos_config:
- lines: set system host-name {{ inventory_hostname_short }}
- match: none
-
-- name: configure simple config command
- vyos.vyos.vyos_config:
- lines: set system host-name foo
- register: result
-
-- assert:
- that:
- - "result.changed == true"
- - "'set system host-name foo' in result.commands"
-
-- name: check simple config command idempontent
- vyos.vyos.vyos_config:
- lines: set system host-name foo
- register: result
-
-- assert:
- that:
- - "result.changed == false"
-
-- name: Delete services
- vyos.vyos.vyos_config: &del
- lines:
- - delete service lldp
- - delete protocols static
-
-- name: Configuring when commands starts with whitespaces
- vyos.vyos.vyos_config:
- src: "{{ role_path }}/tests/cli/config.cfg"
- register: result
-
-- assert:
- that:
- - "result.changed == true"
- - '"set service lldp" in result.commands'
- - '"set protocols static" in result.commands'
-
-- name: Delete services
- vyos.vyos.vyos_config: *del
-
-- name: teardown
- vyos.vyos.vyos_config:
- lines: set system host-name {{ inventory_hostname_short }}
- match: none
-
-- debug: msg="END cli/simple.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_backup.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_backup.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_backup.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_backup.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,114 +0,0 @@
----
-- debug: msg="END cli_config/backup.yaml on connection={{ ansible_connection }}"
-
-- name: delete configurable backup file path
- file:
- path: "{{ item }}"
- state: absent
- with_items:
- - "{{ role_path }}/backup_test_dir/"
- - "{{ role_path }}/backup/backup.cfg"
-
-- name: collect any backup files
- find:
- paths: "{{ role_path }}/backup"
- pattern: "{{ inventory_hostname_short }}_config*"
- register: backup_files
- connection: local
-
-- name: delete backup files
- file:
- path: "{{ item.path }}"
- state: absent
- with_items: "{{backup_files.files|default([])}}"
-
-- name: take config backup
- ansible.netcommon.cli_config:
- backup: true
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: collect any backup files
- find:
- paths: "{{ role_path }}/backup"
- pattern: "{{ inventory_hostname_short }}_config*"
- register: backup_files
- connection: local
-
-- assert:
- that:
- - "backup_files.files is defined"
-
-- name: take configuration backup in custom filename and directory path
- ansible.netcommon.cli_config:
- backup: true
- backup_options:
- filename: backup.cfg
- dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}"
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check if the backup file-1 exist
- find:
- paths: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}/backup.cfg"
- register: backup_file
- connection: local
-
-- assert:
- that:
- - "backup_file.files is defined"
-
-- name: take configuration backup in custom filename
- ansible.netcommon.cli_config:
- backup: true
- backup_options:
- filename: backup.cfg
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check if the backup file-2 exist
- find:
- paths: "{{ role_path }}/backup/backup.cfg"
- register: backup_file
- connection: local
-
-- assert:
- that:
- - "backup_file.files is defined"
-
-- name: take configuration backup in custom path and default filename
- ansible.netcommon.cli_config:
- backup: true
- backup_options:
- dir_path: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}"
- become: true
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: check if the backup file-3 exist
- find:
- paths: "{{ role_path }}/backup_test_dir/{{ inventory_hostname_short }}"
- pattern: "{{ inventory_hostname_short }}_config*"
- register: backup_file
- connection: local
-
-- assert:
- that:
- - "backup_file.files is defined"
-
-- debug: msg="END cli_config/backup.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_basic.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_basic.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_basic.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_basic.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,28 +0,0 @@
----
-- debug: msg="START cli_config/cli_basic.yaml on connection={{ ansible_connection }}"
-
-- name: setup - remove interface description
- ansible.netcommon.cli_config: &rm
- config: delete interfaces loopback lo description
-
-- name: configure device with config
- ansible.netcommon.cli_config: &conf
- config: set interfaces loopback lo description 'this is a test'
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: Idempotence
- ansible.netcommon.cli_config: *conf
- register: result
-
-- assert:
- that:
- - "result.changed == false"
-
-- name: teardown
- ansible.netcommon.cli_config: *rm
-
-- debug: msg="END cli_config/cli_basic.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_comment.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_comment.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_comment.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_config/tests/cli_config/cli_comment.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,30 +0,0 @@
----
-- debug: msg="START cli_config/cli_comment.yaml on connection={{ ansible_connection }}"
-
-- name: setup
- ansible.netcommon.cli_config: &rm
- config: set system host-name {{ inventory_hostname_short }}
-
-- name: configure using comment
- ansible.netcommon.cli_config:
- config: set system host-name foo
- commit_comment: this is a test
- register: result
-
-- assert:
- that:
- - "result.changed == true"
-
-- name: collect system commits
- vyos.vyos.vyos_command:
- commands: show system commit
- register: result
-
-- assert:
- that:
- - "'this is a test' in result.stdout_lines[0][1]"
-
-- name: teardown
- ansible.netcommon.cli_config: *rm
-
-- debug: msg="END cli_config/cli_comment.yaml on connection={{ ansible_connection }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/aliases ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/aliases
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/aliases 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/aliases 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-shippable/vyos/incidental
-network/vyos
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/defaults/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/defaults/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/defaults/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/defaults/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
----
-testcase: "[^_].*"
-test_items: []
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/meta/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/meta/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/meta/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/meta/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
----
-dependencies:
- - incidental_vyos_prepare_tests
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/cli.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/cli.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/cli.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/cli.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
----
-- name: Collect all cli test cases
- find:
- paths: "{{ role_path }}/tests/cli"
- patterns: "{{ testcase }}.yaml"
- use_regex: true
- register: test_cases
- delegate_to: localhost
-
-- name: Set test_items
- set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
-
-- name: Run test case (connection=ansible.netcommon.network_cli)
- include_tasks: "{{ test_case_to_run }}"
- vars:
- ansible_connection: ansible.netcommon.network_cli
- with_items: "{{ test_items }}"
- loop_control:
- loop_var: test_case_to_run
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tasks/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
----
-- {import_tasks: cli.yaml, tags: ['cli']}
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/deleted.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/deleted.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/deleted.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/deleted.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,46 +0,0 @@
----
-- debug:
- msg: "Start vyos_lldp_interfaces deleted integration tests ansible_connection={{ ansible_connection }}"
-
-- include_tasks: _populate.yaml
-
-- block:
- - name: Delete attributes of given LLDP interfaces.
- vyos.vyos.vyos_lldp_interfaces: &deleted
- config:
- - name: 'eth1'
- - name: 'eth2'
- state: deleted
- register: result
-
- - name: Assert that the before dicts were correctly generated
- assert:
- that:
- - "populate | symmetric_difference(result['before']) |length == 0"
-
- - name: Assert that the correct set of commands were generated
- assert:
- that:
- - "deleted['commands'] | symmetric_difference(result['commands']) |length == 0"
-
- - name: Assert that the after dicts were correctly generated
- assert:
- that:
- - "deleted['after'] | symmetric_difference(result['after']) |length == 0"
-
- - name: Delete attributes of given interfaces (IDEMPOTENT)
- vyos.vyos.vyos_lldp_interfaces: *deleted
- register: result
-
- - name: Assert that the previous task was idempotent
- assert:
- that:
- - "result.changed == false"
- - "result.commands|length == 0"
-
- - name: Assert that the before dicts were correctly generated
- assert:
- that:
- - "deleted['after'] | symmetric_difference(result['before']) |length == 0"
- always:
- - include_tasks: _remove_config.yaml
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/empty_config.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/empty_config.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/empty_config.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/empty_config.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,36 +0,0 @@
----
-- debug:
- msg: "START vyos_lldp_interfaces empty_config integration tests on connection={{ ansible_connection }}"
-
-- name: Merged with empty config should give appropriate error message
- vyos.vyos.vyos_lldp_interfaces:
- config:
- state: merged
- register: result
- ignore_errors: true
-
-- assert:
- that:
- - result.msg == 'value of config parameter must not be empty for state merged'
-
-- name: Replaced with empty config should give appropriate error message
- vyos.vyos.vyos_lldp_interfaces:
- config:
- state: replaced
- register: result
- ignore_errors: true
-
-- assert:
- that:
- - result.msg == 'value of config parameter must not be empty for state replaced'
-
-- name: Overridden with empty config should give appropriate error message
- vyos.vyos.vyos_lldp_interfaces:
- config:
- state: overridden
- register: result
- ignore_errors: true
-
-- assert:
- that:
- - result.msg == 'value of config parameter must not be empty for state overridden'
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/merged.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/merged.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/merged.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/merged.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,58 +0,0 @@
----
-- debug:
- msg: "START vyos_lldp_interfaces merged integration tests on connection={{ ansible_connection }}"
-
-- include_tasks: _remove_config.yaml
-
-- block:
- - name: Merge the provided configuration with the exisiting running configuration
- vyos.vyos.vyos_lldp_interfaces: &merged
- config:
- - name: 'eth1'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth2'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
- state: merged
- register: result
-
- - name: Assert that before dicts were correctly generated
- assert:
- that: "merged['before'] | symmetric_difference(result['before']) |length == 0"
-
- - name: Assert that correct set of commands were generated
- assert:
- that:
- - "merged['commands'] | symmetric_difference(result['commands']) |length == 0"
-
- - name: Assert that after dicts was correctly generated
- assert:
- that:
- - "merged['after'] | symmetric_difference(result['after']) |length == 0"
-
- - name: Merge the provided configuration with the existing running configuration (IDEMPOTENT)
- vyos.vyos.vyos_lldp_interfaces: *merged
- register: result
-
- - name: Assert that the previous task was idempotent
- assert:
- that:
- - "result['changed'] == false"
-
- - name: Assert that before dicts were correctly generated
- assert:
- that:
- - "merged['after'] | symmetric_difference(result['before']) |length == 0"
-
- always:
- - include_tasks: _remove_config.yaml
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/overridden.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/overridden.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/overridden.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/overridden.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,49 +0,0 @@
----
-- debug:
- msg: "START vyos_lldp_interfaces overridden integration tests on connection={{ ansible_connection }}"
-
-- include_tasks: _remove_config.yaml
-
-- include_tasks: _populate_intf.yaml
-
-- block:
- - name: Overrides all device configuration with provided configuration
- vyos.vyos.vyos_lldp_interfaces: &overridden
- config:
- - name: 'eth2'
- location:
- elin: '0000000911'
- state: overridden
- register: result
-
- - name: Assert that before dicts were correctly generated
- assert:
- that:
- - "populate_intf | symmetric_difference(result['before']) |length == 0"
-
- - name: Assert that correct commands were generated
- assert:
- that:
- - "overridden['commands'] | symmetric_difference(result['commands']) |length == 0"
-
- - name: Assert that after dicts were correctly generated
- assert:
- that:
- - "overridden['after'] | symmetric_difference(result['after']) |length == 0"
-
- - name: Overrides all device configuration with provided configurations (IDEMPOTENT)
- vyos.vyos.vyos_lldp_interfaces: *overridden
- register: result
-
- - name: Assert that the previous task was idempotent
- assert:
- that:
- - "result['changed'] == false"
-
- - name: Assert that before dicts were correctly generated
- assert:
- that:
- - "overridden['after'] | symmetric_difference(result['before']) |length == 0"
-
- always:
- - include_tasks: _remove_config.yaml
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate_intf.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate_intf.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate_intf.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate_intf.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
----
-- name: Setup
- ansible.netcommon.cli_config:
- config: "{{ lines }}"
- vars:
- lines: |
- set service lldp interface eth2
- set service lldp interface eth2 location civic-based country-code US
- set service lldp interface eth2 location civic-based ca-type 0 ca-value ENGLISH
- set service lldp interface eth2 disable
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_populate.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
----
-- name: Setup
- ansible.netcommon.cli_config:
- config: "{{ lines }}"
- vars:
- lines: |
- set service lldp interface eth1
- set service lldp interface eth1 location civic-based country-code US
- set service lldp interface eth1 location civic-based ca-type 0 ca-value ENGLISH
- set service lldp interface eth2
- set service lldp interface eth2 location coordinate-based latitude 33.524449N
- set service lldp interface eth2 location coordinate-based altitude 2200
- set service lldp interface eth2 location coordinate-based datum WGS84
- set service lldp interface eth2 location coordinate-based longitude 222.267255W
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_remove_config.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_remove_config.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_remove_config.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/_remove_config.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
----
-- name: Remove Config
- ansible.netcommon.cli_config:
- config: "{{ lines }}"
- vars:
- lines: |
- delete service lldp interface
- delete service lldp
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/replaced.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/replaced.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/replaced.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/replaced.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
----
-- debug:
- msg: "START vyos_lldp_interfaces replaced integration tests on connection={{ ansible_connection }}"
-
-- include_tasks: _remove_config.yaml
-
-- include_tasks: _populate.yaml
-
-- block:
- - name: Replace device configurations of listed LLDP interfaces with provided configurations
- vyos.vyos.vyos_lldp_interfaces: &replaced
- config:
- - name: 'eth2'
- enable: false
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth1'
- enable: false
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
- state: replaced
- register: result
-
- - name: Assert that correct set of commands were generated
- assert:
- that:
- - "replaced['commands'] | symmetric_difference(result['commands']) |length == 0"
-
- - name: Assert that before dicts are correctly generated
- assert:
- that:
- - "populate | symmetric_difference(result['before']) |length == 0"
-
- - name: Assert that after dict is correctly generated
- assert:
- that:
- - "replaced['after'] | symmetric_difference(result['after']) |length == 0"
-
- - name: Replace device configurations of listed LLDP interfaces with provided configurarions (IDEMPOTENT)
- vyos.vyos.vyos_lldp_interfaces: *replaced
- register: result
-
- - name: Assert that task was idempotent
- assert:
- that:
- - "result['changed'] == false"
-
- - name: Assert that before dict is correctly generated
- assert:
- that:
- - "replaced['after'] | symmetric_difference(result['before']) |length == 0"
-
- always:
- - include_tasks: _remove_config.yaml
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/rtt.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/rtt.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/rtt.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/tests/cli/rtt.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,57 +0,0 @@
----
-- debug:
- msg: "START vyos_lldp_interfaces round trip integration tests on connection={{ ansible_connection }}"
-
-- include_tasks: _remove_config.yaml
-
-- block:
- - name: Apply the provided configuration (base config)
- vyos.vyos.vyos_lldp_interfaces:
- config:
- - name: 'eth1'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- state: merged
- register: base_config
-
- - name: Gather lldp_interfaces facts
- vyos.vyos.vyos_facts:
- gather_subset:
- - default
- gather_network_resources:
- - lldp_interfaces
-
- - name: Apply the provided configuration (config to be reverted)
- vyos.vyos.vyos_lldp_interfaces:
- config:
- - name: 'eth2'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
- state: merged
- register: result
-
- - name: Assert that changes were applied
- assert:
- that: "{{ round_trip['after'] | symmetric_difference(result['after']) |length == 0 }}"
-
- - name: Revert back to base config using facts round trip
- vyos.vyos.vyos_lldp_interfaces:
- config: "{{ ansible_facts['network_resources']['lldp_interfaces'] }}"
- state: overridden
- register: revert
-
- - name: Assert that config was reverted
- assert:
- that: "{{ base_config['after'] | symmetric_difference(revert['after']) |length == 0 }}"
-
- always:
- - include_tasks: _remove_config.yaml
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/vars/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/vars/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_lldp_interfaces/vars/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_lldp_interfaces/vars/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,130 +0,0 @@
----
-merged:
- before: []
-
-
- commands:
- - "set service lldp interface eth1 location civic-based country-code 'US'"
- - "set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH'"
- - "set service lldp interface eth1"
- - "set service lldp interface eth2 location coordinate-based latitude '33.524449N'"
- - "set service lldp interface eth2 location coordinate-based altitude '2200'"
- - "set service lldp interface eth2 location coordinate-based datum 'WGS84'"
- - "set service lldp interface eth2 location coordinate-based longitude '222.267255W'"
- - "set service lldp interface eth2 location coordinate-based latitude '33.524449N'"
- - "set service lldp interface eth2 location coordinate-based altitude '2200'"
- - "set service lldp interface eth2 location coordinate-based datum 'WGS84'"
- - "set service lldp interface eth2 location coordinate-based longitude '222.267255W'"
- - "set service lldp interface eth2"
-
- after:
- - name: 'eth1'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth2'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
-
-populate:
- - name: 'eth1'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth2'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
-
-replaced:
- commands:
- - "delete service lldp interface eth2 location"
- - "set service lldp interface eth2 'disable'"
- - "set service lldp interface eth2 location civic-based country-code 'US'"
- - "set service lldp interface eth2 location civic-based ca-type 0 ca-value 'ENGLISH'"
- - "delete service lldp interface eth1 location"
- - "set service lldp interface eth1 'disable'"
- - "set service lldp interface eth1 location coordinate-based latitude '33.524449N'"
- - "set service lldp interface eth1 location coordinate-based altitude '2200'"
- - "set service lldp interface eth1 location coordinate-based datum 'WGS84'"
- - "set service lldp interface eth1 location coordinate-based longitude '222.267255W'"
-
- after:
- - name: 'eth2'
- enable: false
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth1'
- enable: false
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
-
-populate_intf:
- - name: 'eth2'
- enable: false
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
-overridden:
- commands:
- - "delete service lldp interface eth2 location"
- - "delete service lldp interface eth2 'disable'"
- - "set service lldp interface eth2 location elin '0000000911'"
-
- after:
- - name: 'eth2'
- location:
- elin: 0000000911
-
-deleted:
- commands:
- - "delete service lldp interface eth1"
- - "delete service lldp interface eth2"
-
- after: []
-
-round_trip:
- after:
- - name: 'eth1'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth2'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_prepare_tests/aliases ansible-core-2.14.18/test/integration/targets/incidental_vyos_prepare_tests/aliases
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_prepare_tests/aliases 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_prepare_tests/aliases 1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-hidden
diff -Nru ansible-core-2.14.16/test/integration/targets/incidental_vyos_prepare_tests/tasks/main.yaml ansible-core-2.14.18/test/integration/targets/incidental_vyos_prepare_tests/tasks/main.yaml
--- ansible-core-2.14.16/test/integration/targets/incidental_vyos_prepare_tests/tasks/main.yaml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/incidental_vyos_prepare_tests/tasks/main.yaml 1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
----
-- name: Ensure required interfaces are present in running-config
- ansible.netcommon.cli_config:
- config: "{{ lines }}"
- vars:
- lines: |
- set interfaces ethernet eth0 address dhcp
- set interfaces ethernet eth0 speed auto
- set interfaces ethernet eth0 duplex auto
- set interfaces ethernet eth1
- set interfaces ethernet eth2
- delete interfaces loopback lo
- ignore_errors: true
diff -Nru ansible-core-2.14.16/test/integration/targets/include_vars-ad-hoc/dir/encrypted.yml ansible-core-2.14.18/test/integration/targets/include_vars-ad-hoc/dir/encrypted.yml
--- ansible-core-2.14.16/test/integration/targets/include_vars-ad-hoc/dir/encrypted.yml 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/include_vars-ad-hoc/dir/encrypted.yml 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,6 @@
+$ANSIBLE_VAULT;1.1;AES256
+31613539636636336264396235633933633839646337323533316638633336653461393036336664
+3939386435313638366366626566346135623932653238360a366261303663343034633865626132
+31646231623630333636383636383833656331643164656366623332396439306132663264663131
+6439633766376261320a616265306430366530363866356433366430633265353739373732646536
+37623661333064306162373463616231636365373231313939373230643936313362
diff -Nru ansible-core-2.14.16/test/integration/targets/include_vars-ad-hoc/runme.sh ansible-core-2.14.18/test/integration/targets/include_vars-ad-hoc/runme.sh
--- ansible-core-2.14.16/test/integration/targets/include_vars-ad-hoc/runme.sh 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/include_vars-ad-hoc/runme.sh 2024-11-04 19:35:24.000000000 +0100
@@ -1,6 +1,22 @@
#!/usr/bin/env bash
-set -eux
+set -eux -o pipefail
-ansible testhost -i ../../inventory -m include_vars -a 'dir/inc.yml' "$@"
-ansible testhost -i ../../inventory -m include_vars -a 'dir=dir' "$@"
+echo "single file include"
+ansible testhost -i ../../inventory -m include_vars -a 'dir/inc.yml' -vvv 2>&1 | grep -q 'porter.*cable'
+
+echo "single file encrypted include"
+ansible testhost -i ../../inventory -m include_vars -a 'dir/encrypted.yml' -vvv --vault-password-file vaultpass > output.txt 2>&1
+
+echo "directory include with encrypted"
+ansible testhost -i ../../inventory -m include_vars -a 'dir=dir' -vvv --vault-password-file vaultpass >> output.txt 2>&1
+
+grep -q 'output has been hidden' output.txt
+
+# all content should be masked if any file is encrypted
+if grep -e 'i am a secret' -e 'porter.*cable' output.txt; then
+ echo "FAIL: vault masking failed"
+ exit 1
+fi
+
+echo PASS
diff -Nru ansible-core-2.14.16/test/integration/targets/include_vars-ad-hoc/vaultpass ansible-core-2.14.18/test/integration/targets/include_vars-ad-hoc/vaultpass
--- ansible-core-2.14.16/test/integration/targets/include_vars-ad-hoc/vaultpass 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/include_vars-ad-hoc/vaultpass 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo supersecurepassword
diff -Nru ansible-core-2.14.16/test/integration/targets/module_utils_facts.system.selinux/tasks/main.yml ansible-core-2.14.18/test/integration/targets/module_utils_facts.system.selinux/tasks/main.yml
--- ansible-core-2.14.16/test/integration/targets/module_utils_facts.system.selinux/tasks/main.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/module_utils_facts.system.selinux/tasks/main.yml 2024-11-04 19:35:24.000000000 +0100
@@ -22,7 +22,7 @@
register: r
- set_fact:
- selinux_policytype: "{{ r.stdout_lines[0] }}"
+ selinux_policytype: "{{ r.stdout_lines[0] | trim }}"
when: r is success and r.stdout_lines
- assert:
diff -Nru ansible-core-2.14.16/test/integration/targets/network_cli/aliases ansible-core-2.14.18/test/integration/targets/network_cli/aliases
--- ansible-core-2.14.16/test/integration/targets/network_cli/aliases 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/network_cli/aliases 1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-# Keeping incidental for efficiency, to avoid spinning up another VM
-shippable/vyos/incidental
-network/vyos
diff -Nru ansible-core-2.14.16/test/integration/targets/network_cli/passworded_user.yml ansible-core-2.14.18/test/integration/targets/network_cli/passworded_user.yml
--- ansible-core-2.14.16/test/integration/targets/network_cli/passworded_user.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/network_cli/passworded_user.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-- hosts: vyos
- gather_facts: false
-
- tasks:
- - name: Run whoami
- vyos.vyos.vyos_command:
- commands:
- - whoami
- register: whoami
-
- - assert:
- that:
- - whoami is successful
- - whoami.stdout_lines[0][0] == 'atester'
diff -Nru ansible-core-2.14.16/test/integration/targets/network_cli/runme.sh ansible-core-2.14.18/test/integration/targets/network_cli/runme.sh
--- ansible-core-2.14.16/test/integration/targets/network_cli/runme.sh 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/network_cli/runme.sh 1970-01-01 01:00:00.000000000 +0100
@@ -1,27 +0,0 @@
-#!/usr/bin/env bash
-set -eux
-export ANSIBLE_ROLES_PATH=../
-
-function cleanup {
- ansible-playbook teardown.yml -i "$INVENTORY_PATH" "$@"
-}
-
-trap cleanup EXIT
-
-ansible-playbook setup.yml -i "$INVENTORY_PATH" "$@"
-
-# We need a nonempty file to override key with (empty file gives a
-# lovely "list index out of range" error)
-foo=$(mktemp)
-echo hello > "$foo"
-
-# We want to ensure that passwords make it to the network connection plugins
-# because they follow a different path than the rest of the codebase.
-# In setup.yml, we create a passworded user, and now we connect as that user
-# to make sure the password we pass here successfully makes it to the plugin.
-ansible-playbook \
- -i "$INVENTORY_PATH" \
- -e ansible_user=atester \
- -e ansible_password=testymctest \
- -e ansible_ssh_private_key_file="$foo" \
- passworded_user.yml
diff -Nru ansible-core-2.14.16/test/integration/targets/network_cli/setup.yml ansible-core-2.14.18/test/integration/targets/network_cli/setup.yml
--- ansible-core-2.14.16/test/integration/targets/network_cli/setup.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/network_cli/setup.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-- hosts: vyos
- connection: ansible.netcommon.network_cli
- become: true
- gather_facts: false
-
- tasks:
- - name: Create user with password
- register: result
- vyos.vyos.vyos_config:
- lines:
- - set system login user atester full-name "Ansible Tester"
- - set system login user atester authentication plaintext-password testymctest
- - set system login user jsmith level admin
- - delete service ssh disable-password-authentication
diff -Nru ansible-core-2.14.16/test/integration/targets/network_cli/teardown.yml ansible-core-2.14.18/test/integration/targets/network_cli/teardown.yml
--- ansible-core-2.14.16/test/integration/targets/network_cli/teardown.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/network_cli/teardown.yml 1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-- hosts: vyos
- connection: ansible.netcommon.network_cli
- become: true
- gather_facts: false
-
- tasks:
- - name: Get rid of user (undo everything from setup.yml)
- register: result
- vyos.vyos.vyos_config:
- lines:
- - delete system login user atester full-name "Ansible Tester"
- - delete system login user atester authentication plaintext-password testymctest
- - delete system login user jsmith level admin
- - set service ssh disable-password-authentication
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/action_plugins/action_sets_no_log.py ansible-core-2.14.18/test/integration/targets/no_log/action_plugins/action_sets_no_log.py
--- ansible-core-2.14.16/test/integration/targets/no_log/action_plugins/action_sets_no_log.py 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/no_log/action_plugins/action_sets_no_log.py 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from ansible.plugins.action import ActionBase
+
+
+class ActionModule(ActionBase):
+ def run(self, tmp=None, task_vars=None):
+ return dict(changed=False, failed=False, msg="action result should be masked", _ansible_no_log="yeppers") # ensure that a truthy non-bool works here
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/ansible_no_log_in_result.yml ansible-core-2.14.18/test/integration/targets/no_log/ansible_no_log_in_result.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/ansible_no_log_in_result.yml 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/no_log/ansible_no_log_in_result.yml 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,13 @@
+- hosts: localhost
+ gather_facts: no
+ tasks:
+ - action_sets_no_log:
+ register: res_action
+
+ - assert:
+ that:
+ - res_action.msg == "action result should be masked"
+
+ - action_sets_no_log:
+ loop: [1, 2, 3]
+ register: res_action
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/dynamic.yml ansible-core-2.14.18/test/integration/targets/no_log/dynamic.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/dynamic.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/no_log/dynamic.yml 2024-11-04 19:35:24.000000000 +0100
@@ -1,27 +1,42 @@
- name: test dynamic no log
hosts: testhost
gather_facts: no
- ignore_errors: yes
tasks:
- name: no loop, task fails, dynamic no_log
- debug:
- msg: "SHOW {{ var_does_not_exist }}"
+ raw: echo {{ var_does_not_exist }}
no_log: "{{ not (unsafe_show_logs|bool) }}"
+ ignore_errors: yes
+ register: result
+
+ - assert:
+ that:
+ - result is failed
+ - result.results is not defined
- name: loop, task succeeds, dynamic does no_log
- debug:
- msg: "SHOW {{ item }}"
+ raw: echo {{ item }}
loop:
- a
- b
- c
no_log: "{{ not (unsafe_show_logs|bool) }}"
+ register: result
+
+ - assert:
+ that:
+ - result.results | length == 3
- name: loop, task fails, dynamic no_log
- debug:
- msg: "SHOW {{ var_does_not_exist }}"
+ raw: echo {{ var_does_not_exist }}
loop:
- a
- b
- c
no_log: "{{ not (unsafe_show_logs|bool) }}"
+ ignore_errors: yes
+ register: result
+
+ - assert:
+ that:
+ - result is failed
+ - result.results is not defined # DT needs result.results | length == 3
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/no_log_config.yml ansible-core-2.14.18/test/integration/targets/no_log/no_log_config.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/no_log_config.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/no_log/no_log_config.yml 2024-11-04 19:35:24.000000000 +0100
@@ -10,4 +10,4 @@
- debug:
- debug:
- loop: '{{ range(3) }}'
+ loop: '{{ range(3) | list }}'
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/no_log_local.yml ansible-core-2.14.18/test/integration/targets/no_log/no_log_local.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/no_log_local.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/no_log/no_log_local.yml 2024-11-04 19:35:24.000000000 +0100
@@ -4,19 +4,22 @@
hosts: testhost
gather_facts: no
tasks:
+ - include_vars: secretvars.yml
+ no_log: true
+
- name: args should be logged in the absence of no_log
- shell: echo "LOG_ME_TASK_SUCCEEDED"
+ shell: echo "{{log_me_prefix}}TASK_SUCCEEDED"
- name: failed args should be logged in the absence of no_log
- shell: echo "LOG_ME_TASK_FAILED"
+ shell: echo "{{log_me_prefix}}TASK_FAILED"
failed_when: true
ignore_errors: true
- name: item args should be logged in the absence of no_log
shell: echo {{ item }}
- with_items: [ "LOG_ME_ITEM", "LOG_ME_SKIPPED", "LOG_ME_ITEM_FAILED" ]
- when: item != "LOG_ME_SKIPPED"
- failed_when: item == "LOG_ME_ITEM_FAILED"
+ with_items: [ "{{log_me_prefix}}ITEM", "{{log_me_prefix}}SKIPPED", "{{log_me_prefix}}ITEM_FAILED" ]
+ when: item != log_me_prefix ~ "SKIPPED"
+ failed_when: item == log_me_prefix ~ "ITEM_FAILED"
ignore_errors: true
- name: args should not be logged when task-level no_log set
@@ -61,7 +64,7 @@
no_log: true
- name: args should be logged when task-level no_log overrides play-level
- shell: echo "LOG_ME_OVERRIDE"
+ shell: echo "{{log_me_prefix}}OVERRIDE"
no_log: false
- name: Add a fake host for next play
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/no_log_suboptions_invalid.yml ansible-core-2.14.18/test/integration/targets/no_log/no_log_suboptions_invalid.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/no_log_suboptions_invalid.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/no_log/no_log_suboptions_invalid.yml 2024-11-04 19:35:24.000000000 +0100
@@ -4,42 +4,45 @@
ignore_errors: yes
tasks:
+ - include_vars: secretvars.yml
+ no_log: true
+
- name: Task with suboptions and invalid parameter
module:
- secret: SUPREME
+ secret: "{{ s201 }}"
invalid: param
subopt_dict:
- str_sub_opt1: IDIOM
+ str_sub_opt1: "{{ s202 }}"
str_sub_opt2: otherstring
nested_subopt:
- n_subopt1: MOCKUP
+ n_subopt1: "{{ s203 }}"
subopt_list:
- - subopt1: EDUCATED
+ - subopt1: "{{ s204 }}"
subopt2: thridstring
- - subopt1: FOOTREST
+ - subopt1: "{{ s205 }}"
- name: Task with suboptions as string with invalid parameter
module:
- secret: FOOTREST
+ secret: "{{ s213 }}"
invalid: param
- subopt_dict: str_sub_opt1=CRAFTY
+ subopt_dict: str_sub_opt1={{ s206 }}
- name: Task with suboptions with dict instead of list
module:
- secret: FELINE
+ secret: "{{ s207 }}"
subopt_dict:
- str_sub_opt1: CRYSTAL
+ str_sub_opt1: "{{ s208 }}"
str_sub_opt2: otherstring
nested_subopt:
- n_subopt1: EXPECTANT
+ n_subopt1: "{{ s209 }}"
subopt_list:
foo: bar
- name: Task with suboptions with incorrect data type
module:
- secret: AGROUND
+ secret: "{{ s210 }}"
subopt_dict: 9068.21361
subopt_list:
- - subopt1: GOLIATH
- - subopt1: FREEFALL
+ - subopt1: "{{ s211 }}"
+ - subopt1: "{{ s212 }}"
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/no_log_suboptions.yml ansible-core-2.14.18/test/integration/targets/no_log/no_log_suboptions.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/no_log_suboptions.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/no_log/no_log_suboptions.yml 2024-11-04 19:35:24.000000000 +0100
@@ -5,20 +5,20 @@
tasks:
- name: Task with suboptions
module:
- secret: GLAMOROUS
+ secret: "{{ s106 }}"
subopt_dict:
- str_sub_opt1: AFTERMATH
+ str_sub_opt1: "{{ s107 }}"
str_sub_opt2: otherstring
nested_subopt:
- n_subopt1: MANPOWER
+ n_subopt1: "{{ s101 }}"
subopt_list:
- - subopt1: UNTAPPED
+ - subopt1: "{{ s102 }}"
subopt2: thridstring
- - subopt1: CONCERNED
+ - subopt1: "{{ s103 }}"
- name: Task with suboptions as string
module:
- secret: MARLIN
- subopt_dict: str_sub_opt1=FLICK
+ secret: "{{ s104 }}"
+ subopt_dict: str_sub_opt1={{ s105 }}
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/runme.sh ansible-core-2.14.18/test/integration/targets/no_log/runme.sh
--- ansible-core-2.14.16/test/integration/targets/no_log/runme.sh 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/no_log/runme.sh 2024-11-04 19:35:24.000000000 +0100
@@ -1,6 +1,12 @@
#!/usr/bin/env bash
-set -eux
+set -eux -o pipefail
+
+# ensure _ansible_no_log returned by actions is actually respected
+ansible-playbook ansible_no_log_in_result.yml -vvvvv > "${OUTPUT_DIR}/output.log" 2> /dev/null
+
+[ "$(grep -c "action result should be masked" "${OUTPUT_DIR}/output.log")" = "0" ]
+[ "$(grep -c "the output has been hidden" "${OUTPUT_DIR}/output.log")" = "4" ]
# This test expects 7 loggable vars and 0 non-loggable ones.
# If either mismatches it fails, run the ansible-playbook command to debug.
@@ -9,18 +15,18 @@
# deal with corner cases with no log and loops
# no log enabled, should produce 6 censored messages
-[ "$(ansible-playbook dynamic.yml -i ../../inventory -vvvvv "$@" -e unsafe_show_logs=no|grep -c 'output has been hidden')" = "6" ]
+[ "$(ansible-playbook dynamic.yml -i ../../inventory -vvvvv "$@" -e unsafe_show_logs=no|grep -c 'output has been hidden')" = "6" ] # DT needs 7
# no log disabled, should produce 0 censored
[ "$(ansible-playbook dynamic.yml -i ../../inventory -vvvvv "$@" -e unsafe_show_logs=yes|grep -c 'output has been hidden')" = "0" ]
# test no log for sub options
-[ "$(ansible-playbook no_log_suboptions.yml -i ../../inventory -vvvvv "$@" | grep -Ec '(MANPOWER|UNTAPPED|CONCERNED|MARLIN|FLICK)')" = "0" ]
+[ "$(ansible-playbook no_log_suboptions.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'SECRET')" = "0" ]
# test invalid data passed to a suboption
-[ "$(ansible-playbook no_log_suboptions_invalid.yml -i ../../inventory -vvvvv "$@" | grep -Ec '(SUPREME|IDIOM|MOCKUP|EDUCATED|FOOTREST|CRAFTY|FELINE|CRYSTAL|EXPECTANT|AGROUND|GOLIATH|FREEFALL)')" = "0" ]
+[ "$(ansible-playbook no_log_suboptions_invalid.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'SECRET')" = "0" ]
# test variations on ANSIBLE_NO_LOG
[ "$(ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "1" ]
[ "$(ANSIBLE_NO_LOG=0 ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "1" ]
-[ "$(ANSIBLE_NO_LOG=1 ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "6" ]
+[ "$(ANSIBLE_NO_LOG=1 ansible-playbook no_log_config.yml -i ../../inventory -vvvvv "$@" | grep -Ec 'the output has been hidden')" = "6" ] # DT needs 5
diff -Nru ansible-core-2.14.16/test/integration/targets/no_log/secretvars.yml ansible-core-2.14.18/test/integration/targets/no_log/secretvars.yml
--- ansible-core-2.14.16/test/integration/targets/no_log/secretvars.yml 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/no_log/secretvars.yml 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,32 @@
+# These values are in a separate vars file and referenced dynamically to avoid spurious counts from contextual error messages
+# that show the playbook contents inline (since unencrypted playbook contents are not considered secret).
+log_me_prefix: LOG_ME_
+
+# Unique values are used for each secret below to ensure that one secret "learned" does not cause another non-secret
+# value to be considered secret simply because they share the same value. A common substring is, however, present in
+# each one to simplify searching for secret values in test output. Having a unique value for each also helps in
+# debugging when unexpected output is encountered.
+
+# secrets for no_log_suboptions.yml
+s101: SECRET101
+s102: SECRET102
+s103: SECRET103
+s104: SECRET104
+s105: SECRET105
+s106: SECRET106
+s107: SECRET107
+
+# secrets for no_log_suboptions_invalid.yml
+s201: SECRET201
+s202: SECRET202
+s203: SECRET203
+s204: SECRET204
+s205: SECRET205
+s206: SECRET206
+s207: SECRET207
+s208: SECRET208
+s209: SECRET209
+s210: SECRET210
+s211: SECRET211
+s212: SECRET212
+s213: SECRET213
diff -Nru ansible-core-2.14.16/test/integration/targets/user/tasks/main.yml ansible-core-2.14.18/test/integration/targets/user/tasks/main.yml
--- ansible-core-2.14.16/test/integration/targets/user/tasks/main.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/user/tasks/main.yml 2024-11-04 19:35:24.000000000 +0100
@@ -36,7 +36,8 @@
- import_tasks: test_ssh_key_passphrase.yml
- import_tasks: test_password_lock.yml
- import_tasks: test_password_lock_new_user.yml
-- import_tasks: test_local.yml
+- include_tasks: test_local.yml
when: not (ansible_distribution == 'openSUSE Leap' and ansible_distribution_version is version('15.4', '>='))
-- import_tasks: test_umask.yml
+- include_tasks: test_umask.yml
when: ansible_facts.system == 'Linux'
+- import_tasks: ssh_keygen.yml
diff -Nru ansible-core-2.14.16/test/integration/targets/user/tasks/ssh_keygen.yml ansible-core-2.14.18/test/integration/targets/user/tasks/ssh_keygen.yml
--- ansible-core-2.14.16/test/integration/targets/user/tasks/ssh_keygen.yml 1970-01-01 01:00:00.000000000 +0100
+++ ansible-core-2.14.18/test/integration/targets/user/tasks/ssh_keygen.yml 2024-11-04 19:35:24.000000000 +0100
@@ -0,0 +1,100 @@
+- name: user generating ssh keys tests
+ become: true
+ vars:
+ home: "{{ (ansible_facts['os_family'] == 'Darwin')|ternary('/Users/ansibulluser/', '/home/ansibulluser/')}}"
+ ssh_key_file: .ssh/ansible_test_rsa
+ pub_file: '{{ssh_key_file}}.pub'
+ key_files:
+ - '{{ssh_key_file}}'
+ - '{{pub_file}}'
+ block:
+ - name: Ensure clean/non existsing ansibulluser
+ user: name=ansibulluser state=absent
+
+ - name: Test creating ssh key creation
+ block:
+ - name: Create user with ssh key
+ user:
+ name: ansibulluser
+ state: present
+ generate_ssh_key: yes
+ ssh_key_file: '{{ ssh_key_file}}'
+
+ - name: check files exist
+ stat:
+ path: '{{home ~ item}}'
+ register: stat_keys
+ loop: '{{ key_files }}'
+
+ - name: ensure they exist
+ assert:
+ that:
+ - stat_keys.results[item].stat.exists
+ loop: [0, 1]
+
+ always:
+ - name: Clean ssh keys
+ file: path={{ home ~ item }} state=absent
+ loop: '{{ key_files }}'
+
+ - name: Ensure clean/non existsing ansibulluser
+ user: name=ansibulluser state=absent
+
+ - name: Ensure we don't break on conflicts
+ block:
+ - name: flag file for test
+ tempfile:
+ register: flagfile
+
+ - name: precreate public .ssh
+ file: path={{home ~ '.ssh'}} state=directory
+
+ - name: setup public key linked to flag file
+ file: path={{home ~ pub_file}} src={{flagfile.path}} state=link
+
+ - name: Create user with ssh key
+ user:
+ name: ansibulluser
+ state: present
+ generate_ssh_key: yes
+ ssh_key_file: '{{ ssh_key_file }}'
+ ignore_errors: true
+ register: user_no_force
+
+ - stat: path={{home ~ pub_file}}
+ register: check_pub
+
+ - name: ensure we didn't overwrite
+ assert:
+ that:
+ - check_pub.stat.exists
+ - check_pub.stat.islnk
+ - check_pub.stat.uid == 0
+
+ - name: Create user with ssh key
+ user:
+ name: ansibulluser
+ state: present
+ generate_ssh_key: yes
+ ssh_key_file: '{{ ssh_key_file }}'
+ force: true
+ ignore_errors: true
+ register: user_force
+
+ - stat: path={{home ~ pub_file}}
+ register: check_pub2
+
+ - name: ensure we failed since we didn't force overwrite
+ assert:
+ that:
+ - user_force is success
+ - check_pub2.stat.exists
+ - not check_pub2.stat.islnk
+ - check_pub2.stat.uid != 0
+ always:
+ - name: Clean up files
+ file: path={{ home ~ item }} state=absent
+ loop: '{{ key_files + [flagfile.path] }}'
+
+ - name: Ensure clean/non existsing ansibulluser
+ user: name=ansibulluser state=absent
diff -Nru ansible-core-2.14.16/test/integration/targets/user/tasks/test_local.yml ansible-core-2.14.18/test/integration/targets/user/tasks/test_local.yml
--- ansible-core-2.14.16/test/integration/targets/user/tasks/test_local.yml 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/integration/targets/user/tasks/test_local.yml 2024-11-04 19:35:24.000000000 +0100
@@ -39,6 +39,15 @@
tags:
- user_test_local_mode
+- name: Ensure no local_ansibulluser
+ user:
+ name: local_ansibulluser
+ state: absent
+ local: yes
+ remove: true
+ tags:
+ - user_test_local_mode
+
- name: Create local_ansibulluser
user:
name: local_ansibulluser
diff -Nru ansible-core-2.14.16/test/lib/ansible_test/_data/completion/network.txt ansible-core-2.14.18/test/lib/ansible_test/_data/completion/network.txt
--- ansible-core-2.14.16/test/lib/ansible_test/_data/completion/network.txt 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/lib/ansible_test/_data/completion/network.txt 2024-11-04 19:35:24.000000000 +0100
@@ -1,2 +1 @@
ios/csr1000v collection=cisco.ios connection=ansible.netcommon.network_cli provider=aws arch=x86_64
-vyos/1.1.8 collection=vyos.vyos connection=ansible.netcommon.network_cli provider=aws arch=x86_64
diff -Nru ansible-core-2.14.16/test/lib/ansible_test/_data/completion/windows.txt ansible-core-2.14.18/test/lib/ansible_test/_data/completion/windows.txt
--- ansible-core-2.14.16/test/lib/ansible_test/_data/completion/windows.txt 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/lib/ansible_test/_data/completion/windows.txt 2024-11-04 19:35:24.000000000 +0100
@@ -1,5 +1,3 @@
-windows/2012 provider=azure arch=x86_64
-windows/2012-R2 provider=azure arch=x86_64
windows/2016 provider=aws arch=x86_64
windows/2019 provider=aws arch=x86_64
windows/2022 provider=aws arch=x86_64
diff -Nru ansible-core-2.14.16/test/lib/ansible_test/_internal/docker_util.py ansible-core-2.14.18/test/lib/ansible_test/_internal/docker_util.py
--- ansible-core-2.14.16/test/lib/ansible_test/_internal/docker_util.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/lib/ansible_test/_internal/docker_util.py 2024-11-04 19:35:24.000000000 +0100
@@ -20,6 +20,8 @@
SubprocessError,
cache,
OutputStream,
+ InternalError,
+ format_command_output,
)
from .util_common import (
@@ -300,7 +302,7 @@
options = ['--volume', '/sys/fs/cgroup:/probe:ro']
cmd = ['sh', '-c', ' && echo "-" && '.join(multi_line_commands)]
- stdout = run_utility_container(args, f'ansible-test-probe-{args.session_name}', cmd, options)[0]
+ stdout, stderr = run_utility_container(args, f'ansible-test-probe-{args.session_name}', cmd, options)
if args.explain:
return ContainerHostProperties(
@@ -313,6 +315,12 @@
blocks = stdout.split('\n-\n')
+ if len(blocks) != len(multi_line_commands):
+ message = f'Unexpected probe output. Expected {len(multi_line_commands)} blocks but found {len(blocks)}.\n'
+ message += format_command_output(stdout, stderr)
+
+ raise InternalError(message.strip())
+
values = blocks[0].split('\n')
audit_parts = values[0].split(' ', 1)
diff -Nru ansible-core-2.14.16/test/lib/ansible_test/_internal/pypi_proxy.py ansible-core-2.14.18/test/lib/ansible_test/_internal/pypi_proxy.py
--- ansible-core-2.14.16/test/lib/ansible_test/_internal/pypi_proxy.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/lib/ansible_test/_internal/pypi_proxy.py 2024-11-04 19:35:24.000000000 +0100
@@ -14,6 +14,7 @@
from .host_configs import (
PosixConfig,
+ DockerConfig,
)
from .util import (
@@ -55,8 +56,14 @@
return # user has overridden the proxy endpoint, there is nothing to provision
versions_needing_proxy: tuple[str, ...] = tuple() # preserved for future use, no versions currently require this
+ containers_needing_proxy: set[str] = {'centos7'}
posix_targets = [target for target in args.targets if isinstance(target, PosixConfig)]
- need_proxy = targets_use_pypi and any(target.python.version in versions_needing_proxy for target in posix_targets)
+ need_proxy = targets_use_pypi and any(
+ target.python.version in versions_needing_proxy or
+ (isinstance(target, DockerConfig) and target.name in containers_needing_proxy)
+ for target in posix_targets
+ )
+
use_proxy = args.pypi_proxy or need_proxy
if not use_proxy:
@@ -69,7 +76,7 @@
display.warning('Unable to use the PyPI proxy because Docker is not available. Installation of packages using `pip` may fail.')
return
- image = 'quay.io/ansible/pypi-test-container:2.0.0'
+ image = 'quay.io/ansible/pypi-test-container:3.1.0'
port = 3141
run_support_container(
diff -Nru ansible-core-2.14.16/test/lib/ansible_test/_internal/util.py ansible-core-2.14.18/test/lib/ansible_test/_internal/util.py
--- ansible-core-2.14.16/test/lib/ansible_test/_internal/util.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/lib/ansible_test/_internal/util.py 2024-11-04 19:35:24.000000000 +0100
@@ -935,14 +935,7 @@
error_callback: t.Optional[c.Callable[[SubprocessError], None]] = None,
) -> None:
message = 'Command "%s" returned exit status %s.\n' % (shlex.join(cmd), status)
-
- if stderr:
- message += '>>> Standard Error\n'
- message += '%s%s\n' % (stderr.strip(), Display.clear)
-
- if stdout:
- message += '>>> Standard Output\n'
- message += '%s%s\n' % (stdout.strip(), Display.clear)
+ message += format_command_output(stdout, stderr)
self.cmd = cmd
self.message = message
@@ -986,6 +979,21 @@
self._callback()
+def format_command_output(stdout: str, stderr: str) -> str:
+ """Return a formatted string containing the given stdout and stderr (if any)."""
+ message = ''
+
+ if stderr := stderr.strip():
+ message += '>>> Standard Error\n'
+ message += f'{stderr}{Display.clear}\n'
+
+ if stdout := stdout.strip():
+ message += '>>> Standard Output\n'
+ message += f'{stdout}{Display.clear}\n'
+
+ return message
+
+
def retry(func: t.Callable[..., TValue], ex_type: t.Type[BaseException] = SubprocessError, sleep: int = 10, attempts: int = 10, warn: bool = True) -> TValue:
"""Retry the specified function on failure."""
for dummy in range(1, attempts):
diff -Nru ansible-core-2.14.16/test/lib/ansible_test/_util/target/setup/bootstrap.sh ansible-core-2.14.18/test/lib/ansible_test/_util/target/setup/bootstrap.sh
--- ansible-core-2.14.16/test/lib/ansible_test/_util/target/setup/bootstrap.sh 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/lib/ansible_test/_util/target/setup/bootstrap.sh 2024-11-04 19:35:24.000000000 +0100
@@ -410,6 +410,15 @@
{
# Required for newer mysql-server packages to install/upgrade on Ubuntu 16.04.
rm -f /usr/sbin/policy-rc.d
+
+ # CentOS 7 is EoL and its official repos are down; we need to the archived ones.
+ if grep -q '^CENTOS_MANTISBT_PROJECT="CentOS-7"$' /etc/os-release
+ then
+ sed -i \
+ -e 's/mirrorlist/#mirrorlist/g' \
+ -e 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' \
+ /etc/yum.repos.d/CentOS-*
+ fi
}
bootstrap_remote()
diff -Nru ansible-core-2.14.16/test/sanity/code-smell/package-data.py ansible-core-2.14.18/test/sanity/code-smell/package-data.py
--- ansible-core-2.14.16/test/sanity/code-smell/package-data.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/sanity/code-smell/package-data.py 2024-11-04 19:35:24.000000000 +0100
@@ -95,7 +95,7 @@
def build(source_dir: str, tmp_dir: str) -> tuple[pathlib.Path, pathlib.Path]:
"""Create a sdist and wheel."""
create = subprocess.run(
- [sys.executable, '-m', 'build', '--no-isolation', '--outdir', tmp_dir],
+ [sys.executable, '-m', 'build', '--outdir', tmp_dir],
stdin=subprocess.DEVNULL,
capture_output=True,
text=True,
diff -Nru ansible-core-2.14.16/test/sanity/ignore.txt ansible-core-2.14.18/test/sanity/ignore.txt
--- ansible-core-2.14.16/test/sanity/ignore.txt 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/sanity/ignore.txt 2024-11-04 19:35:24.000000000 +0100
@@ -183,9 +183,6 @@
test/support/network-integration/collections/ansible_collections/ansible/netcommon/plugins/netconf/default.py pylint:unnecessary-comprehension
test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/cliconf/ios.py pylint:arguments-renamed
test/support/network-integration/collections/ansible_collections/cisco/ios/plugins/modules/ios_config.py pep8:E501
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/cliconf/vyos.py pylint:arguments-renamed
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py pep8:E231
-test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py pylint:disallowed-name
test/support/windows-integration/plugins/action/win_copy.py pylint:used-before-assignment
test/support/windows-integration/collections/ansible_collections/ansible/windows/plugins/module_utils/WebRequest.psm1 pslint!skip
test/support/windows-integration/collections/ansible_collections/ansible/windows/plugins/modules/win_uri.ps1 pslint!skip
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/action/vyos.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/action/vyos.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/action/vyos.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/action/vyos.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,129 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# 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
-
-import sys
-import copy
-
-from ansible_collections.ansible.netcommon.plugins.action.network import (
- ActionModule as ActionNetworkModule,
-)
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
- load_provider,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- vyos_provider_spec,
-)
-from ansible.utils.display import Display
-
-display = Display()
-
-
-class ActionModule(ActionNetworkModule):
- def run(self, tmp=None, task_vars=None):
- del tmp # tmp no longer has any effect
-
- module_name = self._task.action.split(".")[-1]
- self._config_module = True if module_name == "vyos_config" else False
- persistent_connection = self._play_context.connection.split(".")[-1]
- warnings = []
-
- if persistent_connection == "network_cli":
- provider = self._task.args.get("provider", {})
- if any(provider.values()):
- display.warning(
- "provider is unnecessary when using network_cli and will be ignored"
- )
- del self._task.args["provider"]
- elif self._play_context.connection == "local":
- provider = load_provider(vyos_provider_spec, self._task.args)
- pc = copy.deepcopy(self._play_context)
- pc.connection = "ansible.netcommon.network_cli"
- pc.network_os = "vyos.vyos.vyos"
- pc.remote_addr = provider["host"] or self._play_context.remote_addr
- pc.port = int(provider["port"] or self._play_context.port or 22)
- pc.remote_user = (
- provider["username"] or self._play_context.connection_user
- )
- pc.password = provider["password"] or self._play_context.password
- pc.private_key_file = (
- provider["ssh_keyfile"] or self._play_context.private_key_file
- )
-
- connection = self._shared_loader_obj.connection_loader.get(
- "ansible.netcommon.persistent",
- pc,
- sys.stdin,
- task_uuid=self._task._uuid,
- )
-
- # TODO: Remove below code after ansible minimal is cut out
- if connection is None:
- pc.connection = "network_cli"
- pc.network_os = "vyos"
- connection = self._shared_loader_obj.connection_loader.get(
- "persistent", pc, sys.stdin, task_uuid=self._task._uuid
- )
-
- display.vvv(
- "using connection plugin %s (was local)" % pc.connection,
- pc.remote_addr,
- )
-
- command_timeout = (
- int(provider["timeout"])
- if provider["timeout"]
- else connection.get_option("persistent_command_timeout")
- )
- connection.set_options(
- direct={"persistent_command_timeout": command_timeout}
- )
-
- socket_path = connection.run()
- display.vvvv("socket_path: %s" % socket_path, pc.remote_addr)
- if not socket_path:
- return {
- "failed": True,
- "msg": "unable to open shell. Please see: "
- + "https://docs.ansible.com/ansible/latest/network/user_guide/network_debug_troubleshooting.html#category-unable-to-open-shell",
- }
-
- task_vars["ansible_socket"] = socket_path
- warnings.append(
- [
- "connection local support for this module is deprecated and will be removed in version 2.14, use connection %s"
- % pc.connection
- ]
- )
- else:
- return {
- "failed": True,
- "msg": "Connection type %s is not valid for this module"
- % self._play_context.connection,
- }
-
- result = super(ActionModule, self).run(task_vars=task_vars)
- if warnings:
- if "warnings" in result:
- result["warnings"].extend(warnings)
- else:
- result["warnings"] = warnings
- return result
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/cliconf/vyos.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/cliconf/vyos.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/cliconf/vyos.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/cliconf/vyos.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,343 +0,0 @@
-#
-# (c) 2017 Red Hat Inc.
-#
-# 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
-
-DOCUMENTATION = """
----
-author: Ansible Networking Team
-cliconf: vyos
-short_description: Use vyos cliconf to run command on VyOS platform
-description:
- - This vyos plugin provides low level abstraction apis for
- sending and receiving CLI commands from VyOS network devices.
-version_added: "2.4"
-"""
-
-import re
-import json
-
-from collections.abc import Mapping
-
-from ansible.errors import AnsibleConnectionFailure
-from ansible.module_utils._text import to_text
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
- NetworkConfig,
-)
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
- to_list,
-)
-from ansible.plugins.cliconf import CliconfBase
-
-
-class Cliconf(CliconfBase):
- def get_device_info(self):
- device_info = {}
-
- device_info["network_os"] = "vyos"
- reply = self.get("show version")
- data = to_text(reply, errors="surrogate_or_strict").strip()
-
- match = re.search(r"Version:\s*(.*)", data)
- if match:
- device_info["network_os_version"] = match.group(1)
-
- match = re.search(r"HW model:\s*(\S+)", data)
- if match:
- device_info["network_os_model"] = match.group(1)
-
- reply = self.get("show host name")
- device_info["network_os_hostname"] = to_text(
- reply, errors="surrogate_or_strict"
- ).strip()
-
- return device_info
-
- def get_config(self, flags=None, format=None):
- if format:
- option_values = self.get_option_values()
- if format not in option_values["format"]:
- raise ValueError(
- "'format' value %s is invalid. Valid values of format are %s"
- % (format, ", ".join(option_values["format"]))
- )
-
- if not flags:
- flags = []
-
- if format == "text":
- command = "show configuration"
- else:
- command = "show configuration commands"
-
- command += " ".join(to_list(flags))
- command = command.strip()
-
- out = self.send_command(command)
- return out
-
- def edit_config(
- self, candidate=None, commit=True, replace=None, comment=None
- ):
- resp = {}
- operations = self.get_device_operations()
- self.check_edit_config_capability(
- operations, candidate, commit, replace, comment
- )
-
- results = []
- requests = []
- self.send_command("configure")
- for cmd in to_list(candidate):
- if not isinstance(cmd, Mapping):
- cmd = {"command": cmd}
-
- results.append(self.send_command(**cmd))
- requests.append(cmd["command"])
- out = self.get("compare")
- out = to_text(out, errors="surrogate_or_strict")
- diff_config = out if not out.startswith("No changes") else None
-
- if diff_config:
- if commit:
- try:
- self.commit(comment)
- except AnsibleConnectionFailure as e:
- msg = "commit failed: %s" % e.message
- self.discard_changes()
- raise AnsibleConnectionFailure(msg)
- else:
- self.send_command("exit")
- else:
- self.discard_changes()
- else:
- self.send_command("exit")
- if (
- to_text(
- self._connection.get_prompt(), errors="surrogate_or_strict"
- )
- .strip()
- .endswith("#")
- ):
- self.discard_changes()
-
- if diff_config:
- resp["diff"] = diff_config
- resp["response"] = results
- resp["request"] = requests
- return resp
-
- def get(
- self,
- command=None,
- prompt=None,
- answer=None,
- sendonly=False,
- output=None,
- newline=True,
- check_all=False,
- ):
- if not command:
- raise ValueError("must provide value of command to execute")
- if output:
- raise ValueError(
- "'output' value %s is not supported for get" % output
- )
-
- return self.send_command(
- command=command,
- prompt=prompt,
- answer=answer,
- sendonly=sendonly,
- newline=newline,
- check_all=check_all,
- )
-
- def commit(self, comment=None):
- if comment:
- command = 'commit comment "{0}"'.format(comment)
- else:
- command = "commit"
- self.send_command(command)
-
- def discard_changes(self):
- self.send_command("exit discard")
-
- def get_diff(
- self,
- candidate=None,
- running=None,
- diff_match="line",
- diff_ignore_lines=None,
- path=None,
- diff_replace=None,
- ):
- diff = {}
- device_operations = self.get_device_operations()
- option_values = self.get_option_values()
-
- if candidate is None and device_operations["supports_generate_diff"]:
- raise ValueError(
- "candidate configuration is required to generate diff"
- )
-
- if diff_match not in option_values["diff_match"]:
- raise ValueError(
- "'match' value %s in invalid, valid values are %s"
- % (diff_match, ", ".join(option_values["diff_match"]))
- )
-
- if diff_replace:
- raise ValueError("'replace' in diff is not supported")
-
- if diff_ignore_lines:
- raise ValueError("'diff_ignore_lines' in diff is not supported")
-
- if path:
- raise ValueError("'path' in diff is not supported")
-
- set_format = candidate.startswith("set") or candidate.startswith(
- "delete"
- )
- candidate_obj = NetworkConfig(indent=4, contents=candidate)
- if not set_format:
- config = [c.line for c in candidate_obj.items]
- commands = list()
- # this filters out less specific lines
- for item in config:
- for index, entry in enumerate(commands):
- if item.startswith(entry):
- del commands[index]
- break
- commands.append(item)
-
- candidate_commands = [
- "set %s" % cmd.replace(" {", "") for cmd in commands
- ]
-
- else:
- candidate_commands = str(candidate).strip().split("\n")
-
- if diff_match == "none":
- diff["config_diff"] = list(candidate_commands)
- return diff
-
- running_commands = [
- str(c).replace("'", "") for c in running.splitlines()
- ]
-
- updates = list()
- visited = set()
-
- for line in candidate_commands:
- item = str(line).replace("'", "")
-
- if not item.startswith("set") and not item.startswith("delete"):
- raise ValueError(
- "line must start with either `set` or `delete`"
- )
-
- elif item.startswith("set") and item not in running_commands:
- updates.append(line)
-
- elif item.startswith("delete"):
- if not running_commands:
- updates.append(line)
- else:
- item = re.sub(r"delete", "set", item)
- for entry in running_commands:
- if entry.startswith(item) and line not in visited:
- updates.append(line)
- visited.add(line)
-
- diff["config_diff"] = list(updates)
- return diff
-
- def run_commands(self, commands=None, check_rc=True):
- if commands is None:
- raise ValueError("'commands' value is required")
-
- responses = list()
- for cmd in to_list(commands):
- if not isinstance(cmd, Mapping):
- cmd = {"command": cmd}
-
- output = cmd.pop("output", None)
- if output:
- raise ValueError(
- "'output' value %s is not supported for run_commands"
- % output
- )
-
- try:
- out = self.send_command(**cmd)
- except AnsibleConnectionFailure as e:
- if check_rc:
- raise
- out = getattr(e, "err", e)
-
- responses.append(out)
-
- return responses
-
- def get_device_operations(self):
- return {
- "supports_diff_replace": False,
- "supports_commit": True,
- "supports_rollback": False,
- "supports_defaults": False,
- "supports_onbox_diff": True,
- "supports_commit_comment": True,
- "supports_multiline_delimiter": False,
- "supports_diff_match": True,
- "supports_diff_ignore_lines": False,
- "supports_generate_diff": False,
- "supports_replace": False,
- }
-
- def get_option_values(self):
- return {
- "format": ["text", "set"],
- "diff_match": ["line", "none"],
- "diff_replace": [],
- "output": [],
- }
-
- def get_capabilities(self):
- result = super(Cliconf, self).get_capabilities()
- result["rpc"] += [
- "commit",
- "discard_changes",
- "get_diff",
- "run_commands",
- ]
- result["device_operations"] = self.get_device_operations()
- result.update(self.get_option_values())
- return json.dumps(result)
-
- def set_cli_prompt_context(self):
- """
- Make sure we are in the operational cli mode
- :return: None
- """
- if self._connection.connected:
- self._update_cli_prompt_context(
- config_context="#", exit_command="exit discard"
- )
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/doc_fragments/vyos.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-
-class ModuleDocFragment(object):
-
- # Standard files documentation fragment
- DOCUMENTATION = r"""options:
- provider:
- description:
- - B(Deprecated)
- - 'Starting with Ansible 2.5 we recommend using C(connection: network_cli).'
- - For more information please see the L(Network Guide, ../network/getting_started/network_differences.html#multiple-communication-protocols).
- - HORIZONTALLINE
- - A dict object containing connection details.
- type: dict
- suboptions:
- host:
- description:
- - Specifies the DNS host name or address for connecting to the remote device
- over the specified transport. The value of host is used as the destination
- address for the transport.
- type: str
- required: true
- port:
- description:
- - Specifies the port to use when building the connection to the remote device.
- type: int
- default: 22
- username:
- description:
- - Configures the username to use to authenticate the connection to the remote
- device. This value is used to authenticate the SSH session. If the value
- is not specified in the task, the value of environment variable C(ANSIBLE_NET_USERNAME)
- will be used instead.
- type: str
- password:
- description:
- - Specifies the password to use to authenticate the connection to the remote
- device. This value is used to authenticate the SSH session. If the value
- is not specified in the task, the value of environment variable C(ANSIBLE_NET_PASSWORD)
- will be used instead.
- type: str
- timeout:
- description:
- - Specifies the timeout in seconds for communicating with the network device
- for either connecting or sending commands. If the timeout is exceeded before
- the operation is completed, the module will error.
- type: int
- default: 10
- ssh_keyfile:
- description:
- - Specifies the SSH key to use to authenticate the connection to the remote
- device. This value is the path to the key used to authenticate the SSH
- session. If the value is not specified in the task, the value of environment
- variable C(ANSIBLE_NET_SSH_KEYFILE) will be used instead.
- type: path
-notes:
-- For more information on using Ansible to manage network devices see the :ref:`Ansible
- Network Guide <network_guide>`
-"""
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_command.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,223 +0,0 @@
-#!/usr/bin/python
-#
-# 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/>.
-#
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "network",
-}
-
-
-DOCUMENTATION = """module: vyos_command
-author: Nathaniel Case (@Qalthos)
-short_description: Run one or more commands on VyOS devices
-description:
-- The command module allows running one or more commands on remote devices running
- VyOS. This module can also be introspected to validate key parameters before returning
- successfully. If the conditional statements are not met in the wait period, the
- task fails.
-- Certain C(show) commands in VyOS produce many lines of output and use a custom pager
- that can cause this module to hang. If the value of the environment variable C(ANSIBLE_VYOS_TERMINAL_LENGTH)
- is not set, the default number of 10000 is used.
-extends_documentation_fragment:
-- vyos.vyos.vyos
-options:
- commands:
- description:
- - The ordered set of commands to execute on the remote device running VyOS. The
- output from the command execution is returned to the playbook. If the I(wait_for)
- argument is provided, the module is not returned until the condition is satisfied
- or the number of retries has been exceeded.
- required: true
- wait_for:
- description:
- - Specifies what to evaluate from the output of the command and what conditionals
- to apply. This argument will cause the task to wait for a particular conditional
- to be true before moving forward. If the conditional is not true by the configured
- I(retries), the task fails. See examples.
- aliases:
- - waitfor
- match:
- description:
- - The I(match) argument is used in conjunction with the I(wait_for) argument to
- specify the match policy. Valid values are C(all) or C(any). If the value is
- set to C(all) then all conditionals in the wait_for must be satisfied. If the
- value is set to C(any) then only one of the values must be satisfied.
- default: all
- choices:
- - any
- - all
- retries:
- description:
- - Specifies the number of retries a command should be tried before it is considered
- failed. The command is run on the target device every retry and evaluated against
- the I(wait_for) conditionals.
- default: 10
- interval:
- description:
- - Configures the interval in seconds to wait between I(retries) of the command.
- If the command does not pass the specified conditions, the interval indicates
- how long to wait before trying the command again.
- default: 1
-notes:
-- Tested against VyOS 1.1.8 (helium).
-- Running C(show system boot-messages all) will cause the module to hang since VyOS
- is using a custom pager setting to display the output of that command.
-- If a command sent to the device requires answering a prompt, it is possible to pass
- a dict containing I(command), I(answer) and I(prompt). See examples.
-- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html).
-"""
-
-EXAMPLES = """
-tasks:
- - name: show configuration on ethernet devices eth0 and eth1
- vyos_command:
- commands:
- - show interfaces ethernet {{ item }}
- with_items:
- - eth0
- - eth1
-
- - name: run multiple commands and check if version output contains specific version string
- vyos_command:
- commands:
- - show version
- - show hardware cpu
- wait_for:
- - "result[0] contains 'VyOS 1.1.7'"
-
- - name: run command that requires answering a prompt
- vyos_command:
- commands:
- - command: 'rollback 1'
- prompt: 'Proceed with reboot? [confirm][y]'
- answer: y
-"""
-
-RETURN = """
-stdout:
- description: The set of responses from the commands
- returned: always apart from low level errors (such as action plugin)
- type: list
- sample: ['...', '...']
-stdout_lines:
- description: The value of stdout split into a list
- returned: always
- type: list
- sample: [['...', '...'], ['...'], ['...']]
-failed_conditions:
- description: The list of conditionals that have failed
- returned: failed
- type: list
- sample: ['...', '...']
-warnings:
- description: The list of warnings (if any) generated by module based on arguments
- returned: always
- type: list
- sample: ['...', '...']
-"""
-import time
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import (
- Conditional,
-)
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
- transform_commands,
- to_lines,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- run_commands,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- vyos_argument_spec,
-)
-
-
-def parse_commands(module, warnings):
- commands = transform_commands(module)
-
- if module.check_mode:
- for item in list(commands):
- if not item["command"].startswith("show"):
- warnings.append(
- "Only show commands are supported when using check mode, not "
- "executing %s" % item["command"]
- )
- commands.remove(item)
-
- return commands
-
-
-def main():
- spec = dict(
- commands=dict(type="list", required=True),
- wait_for=dict(type="list", aliases=["waitfor"]),
- match=dict(default="all", choices=["all", "any"]),
- retries=dict(default=10, type="int"),
- interval=dict(default=1, type="int"),
- )
-
- spec.update(vyos_argument_spec)
-
- module = AnsibleModule(argument_spec=spec, supports_check_mode=True)
-
- warnings = list()
- result = {"changed": False, "warnings": warnings}
- commands = parse_commands(module, warnings)
- wait_for = module.params["wait_for"] or list()
-
- try:
- conditionals = [Conditional(c) for c in wait_for]
- except AttributeError as exc:
- module.fail_json(msg=to_text(exc))
-
- retries = module.params["retries"]
- interval = module.params["interval"]
- match = module.params["match"]
-
- for _ in range(retries):
- responses = run_commands(module, commands)
-
- for item in list(conditionals):
- if item(responses):
- if match == "any":
- conditionals = list()
- break
- conditionals.remove(item)
-
- if not conditionals:
- break
-
- time.sleep(interval)
-
- if conditionals:
- failed_conditions = [item.raw for item in conditionals]
- msg = "One or more conditional statements have not been satisfied"
- module.fail_json(msg=msg, failed_conditions=failed_conditions)
-
- result.update(
- {"stdout": responses, "stdout_lines": list(to_lines(responses)),}
- )
-
- module.exit_json(**result)
-
-
-if __name__ == "__main__":
- main()
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_config.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,354 +0,0 @@
-#!/usr/bin/python
-#
-# 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/>.
-#
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "network",
-}
-
-
-DOCUMENTATION = """module: vyos_config
-author: Nathaniel Case (@Qalthos)
-short_description: Manage VyOS configuration on remote device
-description:
-- This module provides configuration file management of VyOS devices. It provides
- arguments for managing both the configuration file and state of the active configuration.
- All configuration statements are based on `set` and `delete` commands in the device
- configuration.
-extends_documentation_fragment:
-- vyos.vyos.vyos
-notes:
-- Tested against VyOS 1.1.8 (helium).
-- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html).
-options:
- lines:
- description:
- - The ordered set of configuration lines to be managed and compared with the existing
- configuration on the remote device.
- src:
- description:
- - The C(src) argument specifies the path to the source config file to load. The
- source config file can either be in bracket format or set format. The source
- file can include Jinja2 template variables.
- match:
- description:
- - The C(match) argument controls the method used to match against the current
- active configuration. By default, the desired config is matched against the
- active config and the deltas are loaded. If the C(match) argument is set to
- C(none) the active configuration is ignored and the configuration is always
- loaded.
- default: line
- choices:
- - line
- - none
- backup:
- description:
- - The C(backup) argument will backup the current devices active configuration
- to the Ansible control host prior to making any changes. If the C(backup_options)
- value is not given, the backup file will be located in the backup folder in
- the playbook root directory or role root directory, if playbook is part of an
- ansible role. If the directory does not exist, it is created.
- type: bool
- default: 'no'
- comment:
- description:
- - Allows a commit description to be specified to be included when the configuration
- is committed. If the configuration is not changed or committed, this argument
- is ignored.
- default: configured by vyos_config
- config:
- description:
- - The C(config) argument specifies the base configuration to use to compare against
- the desired configuration. If this value is not specified, the module will
- automatically retrieve the current active configuration from the remote device.
- save:
- description:
- - The C(save) argument controls whether or not changes made to the active configuration
- are saved to disk. This is independent of committing the config. When set
- to True, the active configuration is saved.
- type: bool
- default: 'no'
- backup_options:
- description:
- - This is a dict object containing configurable options related to backup file
- path. The value of this option is read only when C(backup) is set to I(yes),
- if C(backup) is set to I(no) this option will be silently ignored.
- suboptions:
- filename:
- description:
- - The filename to be used to store the backup configuration. If the filename
- is not given it will be generated based on the hostname, current time and
- date in format defined by <hostname>_config.<current-date>@<current-time>
- dir_path:
- description:
- - This option provides the path ending with directory name in which the backup
- configuration file will be stored. If the directory does not exist it will
- be first created and the filename is either the value of C(filename) or
- default filename as described in C(filename) options description. If the
- path value is not given in that case a I(backup) directory will be created
- in the current working directory and backup configuration will be copied
- in C(filename) within I(backup) directory.
- type: path
- type: dict
-"""
-
-EXAMPLES = """
-- name: configure the remote device
- vyos_config:
- lines:
- - set system host-name {{ inventory_hostname }}
- - set service lldp
- - delete service dhcp-server
-
-- name: backup and load from file
- vyos_config:
- src: vyos.cfg
- backup: yes
-
-- name: render a Jinja2 template onto the VyOS router
- vyos_config:
- src: vyos_template.j2
-
-- name: for idempotency, use full-form commands
- vyos_config:
- lines:
- # - set int eth eth2 description 'OUTSIDE'
- - set interface ethernet eth2 description 'OUTSIDE'
-
-- name: configurable backup path
- vyos_config:
- backup: yes
- backup_options:
- filename: backup.cfg
- dir_path: /home/user
-"""
-
-RETURN = """
-commands:
- description: The list of configuration commands sent to the device
- returned: always
- type: list
- sample: ['...', '...']
-filtered:
- description: The list of configuration commands removed to avoid a load failure
- returned: always
- type: list
- sample: ['...', '...']
-backup_path:
- description: The full path to the backup file
- returned: when backup is yes
- type: str
- sample: /playbooks/ansible/backup/vyos_config.2016-07-16@22:28:34
-filename:
- description: The name of the backup file
- returned: when backup is yes and filename is not specified in backup options
- type: str
- sample: vyos_config.2016-07-16@22:28:34
-shortname:
- description: The full path to the backup file excluding the timestamp
- returned: when backup is yes and filename is not specified in backup options
- type: str
- sample: /playbooks/ansible/backup/vyos_config
-date:
- description: The date extracted from the backup file name
- returned: when backup is yes
- type: str
- sample: "2016-07-16"
-time:
- description: The time extracted from the backup file name
- returned: when backup is yes
- type: str
- sample: "22:28:34"
-"""
-import re
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import ConnectionError
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- load_config,
- get_config,
- run_commands,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- vyos_argument_spec,
- get_connection,
-)
-
-
-DEFAULT_COMMENT = "configured by vyos_config"
-
-CONFIG_FILTERS = [
- re.compile(r"set system login user \S+ authentication encrypted-password")
-]
-
-
-def get_candidate(module):
- contents = module.params["src"] or module.params["lines"]
-
- if module.params["src"]:
- contents = format_commands(contents.splitlines())
-
- contents = "\n".join(contents)
- return contents
-
-
-def format_commands(commands):
- """
- This function format the input commands and removes the prepend white spaces
- for command lines having 'set' or 'delete' and it skips empty lines.
- :param commands:
- :return: list of commands
- """
- return [
- line.strip() if line.split()[0] in ("set", "delete") else line
- for line in commands
- if len(line.strip()) > 0
- ]
-
-
-def diff_config(commands, config):
- config = [str(c).replace("'", "") for c in config.splitlines()]
-
- updates = list()
- visited = set()
-
- for line in commands:
- item = str(line).replace("'", "")
-
- if not item.startswith("set") and not item.startswith("delete"):
- raise ValueError("line must start with either `set` or `delete`")
-
- elif item.startswith("set") and item not in config:
- updates.append(line)
-
- elif item.startswith("delete"):
- if not config:
- updates.append(line)
- else:
- item = re.sub(r"delete", "set", item)
- for entry in config:
- if entry.startswith(item) and line not in visited:
- updates.append(line)
- visited.add(line)
-
- return list(updates)
-
-
-def sanitize_config(config, result):
- result["filtered"] = list()
- index_to_filter = list()
- for regex in CONFIG_FILTERS:
- for index, line in enumerate(list(config)):
- if regex.search(line):
- result["filtered"].append(line)
- index_to_filter.append(index)
- # Delete all filtered configs
- for filter_index in sorted(index_to_filter, reverse=True):
- del config[filter_index]
-
-
-def run(module, result):
- # get the current active config from the node or passed in via
- # the config param
- config = module.params["config"] or get_config(module)
-
- # create the candidate config object from the arguments
- candidate = get_candidate(module)
-
- # create loadable config that includes only the configuration updates
- connection = get_connection(module)
- try:
- response = connection.get_diff(
- candidate=candidate,
- running=config,
- diff_match=module.params["match"],
- )
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
-
- commands = response.get("config_diff")
- sanitize_config(commands, result)
-
- result["commands"] = commands
-
- commit = not module.check_mode
- comment = module.params["comment"]
-
- diff = None
- if commands:
- diff = load_config(module, commands, commit=commit, comment=comment)
-
- if result.get("filtered"):
- result["warnings"].append(
- "Some configuration commands were "
- "removed, please see the filtered key"
- )
-
- result["changed"] = True
-
- if module._diff:
- result["diff"] = {"prepared": diff}
-
-
-def main():
- backup_spec = dict(filename=dict(), dir_path=dict(type="path"))
- argument_spec = dict(
- src=dict(type="path"),
- lines=dict(type="list"),
- match=dict(default="line", choices=["line", "none"]),
- comment=dict(default=DEFAULT_COMMENT),
- config=dict(),
- backup=dict(type="bool", default=False),
- backup_options=dict(type="dict", options=backup_spec),
- save=dict(type="bool", default=False),
- )
-
- argument_spec.update(vyos_argument_spec)
-
- mutually_exclusive = [("lines", "src")]
-
- module = AnsibleModule(
- argument_spec=argument_spec,
- mutually_exclusive=mutually_exclusive,
- supports_check_mode=True,
- )
-
- warnings = list()
-
- result = dict(changed=False, warnings=warnings)
-
- if module.params["backup"]:
- result["__backup__"] = get_config(module=module)
-
- if any((module.params["src"], module.params["lines"])):
- run(module, result)
-
- if module.params["save"]:
- diff = run_commands(module, commands=["configure", "compare saved"])[1]
- if diff != "[edit]":
- run_commands(module, commands=["save"])
- result["changed"] = True
- run_commands(module, commands=["exit"])
-
- module.exit_json(**result)
-
-
-if __name__ == "__main__":
- main()
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_facts.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,174 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The module file for vyos_facts
-"""
-
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": [u"preview"],
- "supported_by": "network",
-}
-
-
-DOCUMENTATION = """module: vyos_facts
-short_description: Get facts about vyos devices.
-description:
-- Collects facts from network devices running the vyos operating system. This module
- places the facts gathered in the fact tree keyed by the respective resource name. The
- facts module will always collect a base set of facts from the device and can enable
- or disable collection of additional facts.
-author:
-- Nathaniel Case (@qalthos)
-- Nilashish Chakraborty (@Nilashishc)
-- Rohit Thakur (@rohitthakur2590)
-extends_documentation_fragment:
-- vyos.vyos.vyos
-notes:
-- Tested against VyOS 1.1.8 (helium).
-- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html).
-options:
- gather_subset:
- description:
- - When supplied, this argument will restrict the facts collected to a given subset. Possible
- values for this argument include all, default, config, and neighbors. Can specify
- a list of values to include a larger subset. Values can also be used with an
- initial C(M(!)) to specify that a specific subset should not be collected.
- required: false
- default: '!config'
- gather_network_resources:
- description:
- - When supplied, this argument will restrict the facts collected to a given subset.
- Possible values for this argument include all and the resources like interfaces.
- Can specify a list of values to include a larger subset. Values can also be
- used with an initial C(M(!)) to specify that a specific subset should not be
- collected. Valid subsets are 'all', 'interfaces', 'l3_interfaces', 'lag_interfaces',
- 'lldp_global', 'lldp_interfaces', 'static_routes', 'firewall_rules'.
- required: false
-"""
-
-EXAMPLES = """
-# Gather all facts
-- vyos_facts:
- gather_subset: all
- gather_network_resources: all
-
-# collect only the config and default facts
-- vyos_facts:
- gather_subset: config
-
-# collect everything exception the config
-- vyos_facts:
- gather_subset: "!config"
-
-# Collect only the interfaces facts
-- vyos_facts:
- gather_subset:
- - '!all'
- - '!min'
- gather_network_resources:
- - interfaces
-
-# Do not collect interfaces facts
-- vyos_facts:
- gather_network_resources:
- - "!interfaces"
-
-# Collect interfaces and minimal default facts
-- vyos_facts:
- gather_subset: min
- gather_network_resources: interfaces
-"""
-
-RETURN = """
-ansible_net_config:
- description: The running-config from the device
- returned: when config is configured
- type: str
-ansible_net_commits:
- description: The set of available configuration revisions
- returned: when present
- type: list
-ansible_net_hostname:
- description: The configured system hostname
- returned: always
- type: str
-ansible_net_model:
- description: The device model string
- returned: always
- type: str
-ansible_net_serialnum:
- description: The serial number of the device
- returned: always
- type: str
-ansible_net_version:
- description: The version of the software running
- returned: always
- type: str
-ansible_net_neighbors:
- description: The set of LLDP neighbors
- returned: when interface is configured
- type: list
-ansible_net_gather_subset:
- description: The list of subsets gathered by the module
- returned: always
- type: list
-ansible_net_api:
- description: The name of the transport
- returned: always
- type: str
-ansible_net_python_version:
- description: The Python version Ansible controller is using
- returned: always
- type: str
-ansible_net_gather_network_resources:
- description: The list of fact resource subsets collected from the device
- returned: always
- type: list
-"""
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.facts.facts import (
- FactsArgs,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import (
- Facts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- vyos_argument_spec,
-)
-
-
-def main():
- """
- Main entry point for module execution
-
- :returns: ansible_facts
- """
- argument_spec = FactsArgs.argument_spec
- argument_spec.update(vyos_argument_spec)
-
- module = AnsibleModule(
- argument_spec=argument_spec, supports_check_mode=True
- )
-
- warnings = []
- if module.params["gather_subset"] == "!config":
- warnings.append(
- "default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards"
- )
-
- result = Facts(module).get_facts()
-
- ansible_facts, additional_warnings = result
- warnings.extend(additional_warnings)
-
- module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
-
-
-if __name__ == "__main__":
- main()
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_lldp_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_lldp_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_lldp_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/modules/vyos_lldp_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,513 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The module file for vyos_lldp_interfaces
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- "metadata_version": "1.1",
- "status": ["preview"],
- "supported_by": "network",
-}
-
-DOCUMENTATION = """module: vyos_lldp_interfaces
-short_description: Manages attributes of lldp interfaces on VyOS devices.
-description: This module manages attributes of lldp interfaces on VyOS network devices.
-notes:
-- Tested against VyOS 1.1.8 (helium).
-- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html).
-author:
-- Rohit Thakur (@rohitthakur2590)
-options:
- config:
- description: A list of lldp interfaces configurations.
- type: list
- suboptions:
- name:
- description:
- - Name of the lldp interface.
- type: str
- required: true
- enable:
- description:
- - to disable lldp on the interface.
- type: bool
- default: true
- location:
- description:
- - LLDP-MED location data.
- type: dict
- suboptions:
- civic_based:
- description:
- - Civic-based location data.
- type: dict
- suboptions:
- ca_info:
- description: LLDP-MED address info
- type: list
- suboptions:
- ca_type:
- description: LLDP-MED Civic Address type.
- type: int
- required: true
- ca_value:
- description: LLDP-MED Civic Address value.
- type: str
- required: true
- country_code:
- description: Country Code
- type: str
- required: true
- coordinate_based:
- description:
- - Coordinate-based location.
- type: dict
- suboptions:
- altitude:
- description: Altitude in meters.
- type: int
- datum:
- description: Coordinate datum type.
- type: str
- choices:
- - WGS84
- - NAD83
- - MLLW
- latitude:
- description: Latitude.
- type: str
- required: true
- longitude:
- description: Longitude.
- type: str
- required: true
- elin:
- description: Emergency Call Service ELIN number (between 10-25 numbers).
- type: str
- state:
- description:
- - The state of the configuration after module completion.
- type: str
- choices:
- - merged
- - replaced
- - overridden
- - deleted
- default: merged
-"""
-EXAMPLES = """
-# Using merged
-#
-# Before state:
-# -------------
-#
-# vyos@vyos:~$ show configuration commands | grep lldp
-#
-- name: Merge provided configuration with device configuration
- vyos_lldp_interfaces:
- config:
- - name: 'eth1'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth2'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
- state: merged
-#
-#
-# -------------------------
-# Module Execution Result
-# -------------------------
-#
-# before": []
-#
-# "commands": [
-# "set service lldp interface eth1 location civic-based country-code 'US'",
-# "set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH'",
-# "set service lldp interface eth1",
-# "set service lldp interface eth2 location coordinate-based latitude '33.524449N'",
-# "set service lldp interface eth2 location coordinate-based altitude '2200'",
-# "set service lldp interface eth2 location coordinate-based datum 'WGS84'",
-# "set service lldp interface eth2 location coordinate-based longitude '222.267255W'",
-# "set service lldp interface eth2 location coordinate-based latitude '33.524449N'",
-# "set service lldp interface eth2 location coordinate-based altitude '2200'",
-# "set service lldp interface eth2 location coordinate-based datum 'WGS84'",
-# "set service lldp interface eth2 location coordinate-based longitude '222.267255W'",
-# "set service lldp interface eth2"
-#
-# "after": [
-# {
-# "location": {
-# "coordinate_based": {
-# "altitude": 2200,
-# "datum": "WGS84",
-# "latitude": "33.524449N",
-# "longitude": "222.267255W"
-# }
-# },
-# "name": "eth2"
-# },
-# {
-# "location": {
-# "civic_based": {
-# "ca_info": [
-# {
-# "ca_type": 0,
-# "ca_value": "ENGLISH"
-# }
-# ],
-# "country_code": "US"
-# }
-# },
-# "name": "eth1"
-# }
-# ],
-#
-# After state:
-# -------------
-#
-# vyos@vyos:~$ show configuration commands | grep lldp
-# set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH'
-# set service lldp interface eth1 location civic-based country-code 'US'
-# set service lldp interface eth2 location coordinate-based altitude '2200'
-# set service lldp interface eth2 location coordinate-based datum 'WGS84'
-# set service lldp interface eth2 location coordinate-based latitude '33.524449N'
-# set service lldp interface eth2 location coordinate-based longitude '222.267255W'
-
-
-# Using replaced
-#
-# Before state:
-# -------------
-#
-# vyos@vyos:~$ show configuration commands | grep lldp
-# set service lldp interface eth1 location civic-based ca-type 0 ca-value 'ENGLISH'
-# set service lldp interface eth1 location civic-based country-code 'US'
-# set service lldp interface eth2 location coordinate-based altitude '2200'
-# set service lldp interface eth2 location coordinate-based datum 'WGS84'
-# set service lldp interface eth2 location coordinate-based latitude '33.524449N'
-# set service lldp interface eth2 location coordinate-based longitude '222.267255W'
-#
-- name: Replace device configurations of listed LLDP interfaces with provided configurations
- vyos_lldp_interfaces:
- config:
- - name: 'eth2'
- location:
- civic_based:
- country_code: 'US'
- ca_info:
- - ca_type: 0
- ca_value: 'ENGLISH'
-
- - name: 'eth1'
- location:
- coordinate_based:
- altitude: 2200
- datum: 'WGS84'
- longitude: '222.267255W'
- latitude: '33.524449N'
- state: replaced
-#
-#
-# -------------------------
-# Module Execution Result
-# -------------------------
-#
-# "before": [
-# {
-# "location": {
-# "coordinate_based": {
-# "altitude": 2200,
-# "datum": "WGS84",
-# "latitude": "33.524449N",
-# "longitude": "222.267255W"
-# }
-# },
-# "name": "eth2"
-# },
-# {
-# "location": {
-# "civic_based": {
-# "ca_info": [
-# {
-# "ca_type": 0,
-# "ca_value": "ENGLISH"
-# }
-# ],
-# "country_code": "US"
-# }
-# },
-# "name": "eth1"
-# }
-# ]
-#
-# "commands": [
-# "delete service lldp interface eth2 location",
-# "set service lldp interface eth2 'disable'",
-# "set service lldp interface eth2 location civic-based country-code 'US'",
-# "set service lldp interface eth2 location civic-based ca-type 0 ca-value 'ENGLISH'",
-# "delete service lldp interface eth1 location",
-# "set service lldp interface eth1 'disable'",
-# "set service lldp interface eth1 location coordinate-based latitude '33.524449N'",
-# "set service lldp interface eth1 location coordinate-based altitude '2200'",
-# "set service lldp interface eth1 location coordinate-based datum 'WGS84'",
-# "set service lldp interface eth1 location coordinate-based longitude '222.267255W'"
-# ]
-#
-# "after": [
-# {
-# "location": {
-# "civic_based": {
-# "ca_info": [
-# {
-# "ca_type": 0,
-# "ca_value": "ENGLISH"
-# }
-# ],
-# "country_code": "US"
-# }
-# },
-# "name": "eth2"
-# },
-# {
-# "location": {
-# "coordinate_based": {
-# "altitude": 2200,
-# "datum": "WGS84",
-# "latitude": "33.524449N",
-# "longitude": "222.267255W"
-# }
-# },
-# "name": "eth1"
-# }
-# ]
-#
-# After state:
-# -------------
-#
-# vyos@vyos:~$ show configuration commands | grep lldp
-# set service lldp interface eth1 'disable'
-# set service lldp interface eth1 location coordinate-based altitude '2200'
-# set service lldp interface eth1 location coordinate-based datum 'WGS84'
-# set service lldp interface eth1 location coordinate-based latitude '33.524449N'
-# set service lldp interface eth1 location coordinate-based longitude '222.267255W'
-# set service lldp interface eth2 'disable'
-# set service lldp interface eth2 location civic-based ca-type 0 ca-value 'ENGLISH'
-# set service lldp interface eth2 location civic-based country-code 'US'
-
-
-# Using overridden
-#
-# Before state
-# --------------
-#
-# vyos@vyos:~$ show configuration commands | grep lldp
-# set service lldp interface eth1 'disable'
-# set service lldp interface eth1 location coordinate-based altitude '2200'
-# set service lldp interface eth1 location coordinate-based datum 'WGS84'
-# set service lldp interface eth1 location coordinate-based latitude '33.524449N'
-# set service lldp interface eth1 location coordinate-based longitude '222.267255W'
-# set service lldp interface eth2 'disable'
-# set service lldp interface eth2 location civic-based ca-type 0 ca-value 'ENGLISH'
-# set service lldp interface eth2 location civic-based country-code 'US'
-#
-- name: Overrides all device configuration with provided configuration
- vyos_lag_interfaces:
- config:
- - name: 'eth2'
- location:
- elin: 0000000911
-
- state: overridden
-#
-#
-# -------------------------
-# Module Execution Result
-# -------------------------
-#
-# "before": [
-# {
-# "enable": false,
-# "location": {
-# "civic_based": {
-# "ca_info": [
-# {
-# "ca_type": 0,
-# "ca_value": "ENGLISH"
-# }
-# ],
-# "country_code": "US"
-# }
-# },
-# "name": "eth2"
-# },
-# {
-# "enable": false,
-# "location": {
-# "coordinate_based": {
-# "altitude": 2200,
-# "datum": "WGS84",
-# "latitude": "33.524449N",
-# "longitude": "222.267255W"
-# }
-# },
-# "name": "eth1"
-# }
-# ]
-#
-# "commands": [
-# "delete service lldp interface eth2 location",
-# "delete service lldp interface eth2 disable",
-# "set service lldp interface eth2 location elin 0000000911"
-#
-#
-# "after": [
-# {
-# "location": {
-# "elin": 0000000911
-# },
-# "name": "eth2"
-# }
-# ]
-#
-#
-# After state
-# ------------
-#
-# vyos@vyos# run show configuration commands | grep lldp
-# set service lldp interface eth2 location elin '0000000911'
-
-
-# Using deleted
-#
-# Before state
-# -------------
-#
-# vyos@vyos# run show configuration commands | grep lldp
-# set service lldp interface eth2 location elin '0000000911'
-#
-- name: Delete lldp interface attributes of given interfaces.
- vyos_lag_interfaces:
- config:
- - name: 'eth2'
- state: deleted
-#
-#
-# ------------------------
-# Module Execution Results
-# ------------------------
-#
- "before": [
- {
- "location": {
- "elin": 0000000911
- },
- "name": "eth2"
- }
- ]
-# "commands": [
-# "commands": [
-# "delete service lldp interface eth2"
-# ]
-#
-# "after": []
-# After state
-# ------------
-# vyos@vyos# run show configuration commands | grep lldp
-# set service 'lldp'
-
-
-"""
-RETURN = """
-before:
- description: The configuration as structured data prior to module invocation.
- returned: always
- type: list
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
-after:
- description: The configuration as structured data after module completion.
- returned: when changed
- type: list
- sample: >
- The configuration returned will always be in the same format
- of the parameters above.
-commands:
- description: The set of commands pushed to the remote device.
- returned: always
- type: list
- sample:
- - "set service lldp interface eth2 'disable'"
- - "delete service lldp interface eth1 location"
-"""
-
-
-from ansible.module_utils.basic import AnsibleModule
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_interfaces.lldp_interfaces import (
- Lldp_interfacesArgs,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.config.lldp_interfaces.lldp_interfaces import (
- Lldp_interfaces,
-)
-
-
-def main():
- """
- Main entry point for module execution
-
- :returns: the result form module invocation
- """
- required_if = [
- ("state", "merged", ("config",)),
- ("state", "replaced", ("config",)),
- ("state", "overridden", ("config",)),
- ]
- module = AnsibleModule(
- argument_spec=Lldp_interfacesArgs.argument_spec,
- required_if=required_if,
- supports_check_mode=True,
- )
-
- result = Lldp_interfaces(module).execute_module()
- module.exit_json(**result)
-
-
-if __name__ == "__main__":
- main()
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/facts/facts.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/facts/facts.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/facts/facts.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/facts/facts.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The arg spec for the vyos facts module.
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class FactsArgs(object): # pylint: disable=R0903
- """ The arg spec for the vyos facts module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "gather_subset": dict(default=["!config"], type="list"),
- "gather_network_resources": dict(type="list"),
- }
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/firewall_rules/firewall_rules.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,263 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The arg spec for the vyos_firewall_rules module
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class Firewall_rulesArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_firewall_rules module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "elements": "dict",
- "options": {
- "afi": {
- "choices": ["ipv4", "ipv6"],
- "required": True,
- "type": "str",
- },
- "rule_sets": {
- "elements": "dict",
- "options": {
- "default_action": {
- "choices": ["drop", "reject", "accept"],
- "type": "str",
- },
- "description": {"type": "str"},
- "enable_default_log": {"type": "bool"},
- "name": {"type": "str"},
- "rules": {
- "elements": "dict",
- "options": {
- "action": {
- "choices": [
- "drop",
- "reject",
- "accept",
- "inspect",
- ],
- "type": "str",
- },
- "description": {"type": "str"},
- "destination": {
- "options": {
- "address": {"type": "str"},
- "group": {
- "options": {
- "address_group": {
- "type": "str"
- },
- "network_group": {
- "type": "str"
- },
- "port_group": {"type": "str"},
- },
- "type": "dict",
- },
- "port": {"type": "str"},
- },
- "type": "dict",
- },
- "disabled": {"type": "bool"},
- "fragment": {
- "choices": [
- "match-frag",
- "match-non-frag",
- ],
- "type": "str",
- },
- "icmp": {
- "options": {
- "code": {"type": "int"},
- "type": {"type": "int"},
- "type_name": {
- "choices": [
- "any",
- "echo-reply",
- "destination-unreachable",
- "network-unreachable",
- "host-unreachable",
- "protocol-unreachable",
- "port-unreachable",
- "fragmentation-needed",
- "source-route-failed",
- "network-unknown",
- "host-unknown",
- "network-prohibited",
- "host-prohibited",
- "TOS-network-unreachable",
- "TOS-host-unreachable",
- "communication-prohibited",
- "host-precedence-violation",
- "precedence-cutoff",
- "source-quench",
- "redirect",
- "network-redirect",
- "host-redirect",
- "TOS-network-redirect",
- "TOS-host-redirect",
- "echo-request",
- "router-advertisement",
- "router-solicitation",
- "time-exceeded",
- "ttl-zero-during-transit",
- "ttl-zero-during-reassembly",
- "parameter-problem",
- "ip-header-bad",
- "required-option-missing",
- "timestamp-request",
- "timestamp-reply",
- "address-mask-request",
- "address-mask-reply",
- "ping",
- "pong",
- "ttl-exceeded",
- ],
- "type": "str",
- },
- },
- "type": "dict",
- },
- "ipsec": {
- "choices": ["match-ipsec", "match-none"],
- "type": "str",
- },
- "limit": {
- "options": {
- "burst": {"type": "int"},
- "rate": {
- "options": {
- "number": {"type": "int"},
- "unit": {"type": "str"},
- },
- "type": "dict",
- },
- },
- "type": "dict",
- },
- "number": {"required": True, "type": "int"},
- "p2p": {
- "elements": "dict",
- "options": {
- "application": {
- "choices": [
- "all",
- "applejuice",
- "bittorrent",
- "directconnect",
- "edonkey",
- "gnutella",
- "kazaa",
- ],
- "type": "str",
- }
- },
- "type": "list",
- },
- "protocol": {"type": "str"},
- "recent": {
- "options": {
- "count": {"type": "int"},
- "time": {"type": "int"},
- },
- "type": "dict",
- },
- "source": {
- "options": {
- "address": {"type": "str"},
- "group": {
- "options": {
- "address_group": {
- "type": "str"
- },
- "network_group": {
- "type": "str"
- },
- "port_group": {"type": "str"},
- },
- "type": "dict",
- },
- "mac_address": {"type": "str"},
- "port": {"type": "str"},
- },
- "type": "dict",
- },
- "state": {
- "options": {
- "established": {"type": "bool"},
- "invalid": {"type": "bool"},
- "new": {"type": "bool"},
- "related": {"type": "bool"},
- },
- "type": "dict",
- },
- "tcp": {
- "options": {"flags": {"type": "str"}},
- "type": "dict",
- },
- "time": {
- "options": {
- "monthdays": {"type": "str"},
- "startdate": {"type": "str"},
- "starttime": {"type": "str"},
- "stopdate": {"type": "str"},
- "stoptime": {"type": "str"},
- "utc": {"type": "bool"},
- "weekdays": {"type": "str"},
- },
- "type": "dict",
- },
- },
- "type": "list",
- },
- },
- "type": "list",
- },
- },
- "type": "list",
- },
- "running_config": {"type": "str"},
- "state": {
- "choices": [
- "merged",
- "replaced",
- "overridden",
- "deleted",
- "gathered",
- "rendered",
- "parsed",
- ],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/interfaces/interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,69 +0,0 @@
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The arg spec for the vyos_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class InterfacesArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "elements": "dict",
- "options": {
- "description": {"type": "str"},
- "duplex": {"choices": ["full", "half", "auto"]},
- "enabled": {"default": True, "type": "bool"},
- "mtu": {"type": "int"},
- "name": {"required": True, "type": "str"},
- "speed": {
- "choices": ["auto", "10", "100", "1000", "2500", "10000"],
- "type": "str",
- },
- "vifs": {
- "elements": "dict",
- "options": {
- "vlan_id": {"type": "int"},
- "description": {"type": "str"},
- "enabled": {"default": True, "type": "bool"},
- "mtu": {"type": "int"},
- },
- "type": "list",
- },
- },
- "type": "list",
- },
- "state": {
- "choices": ["merged", "replaced", "overridden", "deleted"],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/l3_interfaces/l3_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/l3_interfaces/l3_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/l3_interfaces/l3_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/l3_interfaces/l3_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,81 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The arg spec for the vyos_l3_interfaces module
-"""
-
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class L3_interfacesArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_l3_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "elements": "dict",
- "options": {
- "ipv4": {
- "elements": "dict",
- "options": {"address": {"type": "str"}},
- "type": "list",
- },
- "ipv6": {
- "elements": "dict",
- "options": {"address": {"type": "str"}},
- "type": "list",
- },
- "name": {"required": True, "type": "str"},
- "vifs": {
- "elements": "dict",
- "options": {
- "ipv4": {
- "elements": "dict",
- "options": {"address": {"type": "str"}},
- "type": "list",
- },
- "ipv6": {
- "elements": "dict",
- "options": {"address": {"type": "str"}},
- "type": "list",
- },
- "vlan_id": {"type": "int"},
- },
- "type": "list",
- },
- },
- "type": "list",
- },
- "state": {
- "choices": ["merged", "replaced", "overridden", "deleted"],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lag_interfaces/lag_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,80 +0,0 @@
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The arg spec for the vyos_lag_interfaces module
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class Lag_interfacesArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_lag_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "elements": "dict",
- "options": {
- "arp_monitor": {
- "options": {
- "interval": {"type": "int"},
- "target": {"type": "list"},
- },
- "type": "dict",
- },
- "hash_policy": {
- "choices": ["layer2", "layer2+3", "layer3+4"],
- "type": "str",
- },
- "members": {
- "elements": "dict",
- "options": {"member": {"type": "str"}},
- "type": "list",
- },
- "mode": {
- "choices": [
- "802.3ad",
- "active-backup",
- "broadcast",
- "round-robin",
- "transmit-load-balance",
- "adaptive-load-balance",
- "xor-hash",
- ],
- "type": "str",
- },
- "name": {"required": True, "type": "str"},
- "primary": {"type": "str"},
- },
- "type": "list",
- },
- "state": {
- "choices": ["merged", "replaced", "overridden", "deleted"],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_global/lldp_global.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,56 +0,0 @@
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-
-"""
-The arg spec for the vyos_lldp_global module
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class Lldp_globalArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_lldp_global module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "options": {
- "address": {"type": "str"},
- "enable": {"type": "bool"},
- "legacy_protocols": {
- "choices": ["cdp", "edp", "fdp", "sonmp"],
- "type": "list",
- },
- "snmp": {"type": "str"},
- },
- "type": "dict",
- },
- "state": {
- "choices": ["merged", "replaced", "deleted"],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/lldp_interfaces/lldp_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,89 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The arg spec for the vyos_lldp_interfaces module
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class Lldp_interfacesArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_lldp_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "elements": "dict",
- "options": {
- "enable": {"default": True, "type": "bool"},
- "location": {
- "options": {
- "civic_based": {
- "options": {
- "ca_info": {
- "elements": "dict",
- "options": {
- "ca_type": {"type": "int"},
- "ca_value": {"type": "str"},
- },
- "type": "list",
- },
- "country_code": {
- "required": True,
- "type": "str",
- },
- },
- "type": "dict",
- },
- "coordinate_based": {
- "options": {
- "altitude": {"type": "int"},
- "datum": {
- "choices": ["WGS84", "NAD83", "MLLW"],
- "type": "str",
- },
- "latitude": {"required": True, "type": "str"},
- "longitude": {"required": True, "type": "str"},
- },
- "type": "dict",
- },
- "elin": {"type": "str"},
- },
- "type": "dict",
- },
- "name": {"required": True, "type": "str"},
- },
- "type": "list",
- },
- "state": {
- "choices": ["merged", "replaced", "overridden", "deleted"],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/static_routes/static_routes.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/static_routes/static_routes.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/static_routes/static_routes.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/argspec/static_routes/static_routes.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,99 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#############################################
-# WARNING #
-#############################################
-#
-# This file is auto generated by the resource
-# module builder playbook.
-#
-# Do not edit this file manually.
-#
-# Changes to this file will be over written
-# by the resource module builder.
-#
-# Changes should be made in the model used to
-# generate this file or in the resource module
-# builder template.
-#
-#############################################
-"""
-The arg spec for the vyos_static_routes module
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-class Static_routesArgs(object): # pylint: disable=R0903
- """The arg spec for the vyos_static_routes module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- "config": {
- "elements": "dict",
- "options": {
- "address_families": {
- "elements": "dict",
- "options": {
- "afi": {
- "choices": ["ipv4", "ipv6"],
- "required": True,
- "type": "str",
- },
- "routes": {
- "elements": "dict",
- "options": {
- "blackhole_config": {
- "options": {
- "distance": {"type": "int"},
- "type": {"type": "str"},
- },
- "type": "dict",
- },
- "dest": {"required": True, "type": "str"},
- "next_hops": {
- "elements": "dict",
- "options": {
- "admin_distance": {"type": "int"},
- "enabled": {"type": "bool"},
- "forward_router_address": {
- "required": True,
- "type": "str",
- },
- "interface": {"type": "str"},
- },
- "type": "list",
- },
- },
- "type": "list",
- },
- },
- "type": "list",
- }
- },
- "type": "list",
- },
- "running_config": {"type": "str"},
- "state": {
- "choices": [
- "merged",
- "replaced",
- "overridden",
- "deleted",
- "gathered",
- "rendered",
- "parsed",
- ],
- "default": "merged",
- "type": "str",
- },
- } # pylint: disable=C0301
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,438 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos_lldp_interfaces class
-It is in this file where the current configuration (as dict)
-is compared to the provided configuration (as dict) and the command set
-necessary to bring the current configuration to it's desired end-state is
-created
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
- ConfigBase,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import (
- Facts,
-)
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
- to_list,
- dict_diff,
-)
-from ansible.module_utils.six import iteritems
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import (
- search_obj_in_list,
- search_dict_tv_in_list,
- key_value_in_dict,
- is_dict_element_present,
-)
-
-
-class Lldp_interfaces(ConfigBase):
- """
- The vyos_lldp_interfaces class
- """
-
- gather_subset = [
- "!all",
- "!min",
- ]
-
- gather_network_resources = [
- "lldp_interfaces",
- ]
-
- params = ["enable", "location", "name"]
-
- def __init__(self, module):
- super(Lldp_interfaces, self).__init__(module)
-
- def get_lldp_interfaces_facts(self):
- """ Get the 'facts' (the current configuration)
-
- :rtype: A dictionary
- :returns: The current configuration as a dictionary
- """
- facts, _warnings = Facts(self._module).get_facts(
- self.gather_subset, self.gather_network_resources
- )
- lldp_interfaces_facts = facts["ansible_network_resources"].get(
- "lldp_interfaces"
- )
- if not lldp_interfaces_facts:
- return []
- return lldp_interfaces_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {"changed": False}
- commands = list()
- warnings = list()
- existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
- commands.extend(self.set_config(existing_lldp_interfaces_facts))
- if commands:
- if self._module.check_mode:
- resp = self._connection.edit_config(commands, commit=False)
- else:
- resp = self._connection.edit_config(commands)
- result["changed"] = True
-
- result["commands"] = commands
-
- if self._module._diff:
- result["diff"] = resp["diff"] if result["changed"] else None
-
- changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
- result["before"] = existing_lldp_interfaces_facts
- if result["changed"]:
- result["after"] = changed_lldp_interfaces_facts
-
- result["warnings"] = warnings
- return result
-
- def set_config(self, existing_lldp_interfaces_facts):
- """ Collect the configuration from the args passed to the module,
- collect the current configuration (as a dict from facts)
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- want = self._module.params["config"]
- have = existing_lldp_interfaces_facts
- resp = self.set_state(want, have)
- return to_list(resp)
-
- def set_state(self, want, have):
- """ Select the appropriate function based on the state provided
-
- :param want: the desired configuration as a dictionary
- :param have: the current configuration as a dictionary
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
- state = self._module.params["state"]
- if state in ("merged", "replaced", "overridden") and not want:
- self._module.fail_json(
- msg="value of config parameter must not be empty for state {0}".format(
- state
- )
- )
- if state == "overridden":
- commands.extend(self._state_overridden(want=want, have=have))
- elif state == "deleted":
- if want:
- for item in want:
- name = item["name"]
- have_item = search_obj_in_list(name, have)
- commands.extend(
- self._state_deleted(want=None, have=have_item)
- )
- else:
- for have_item in have:
- commands.extend(
- self._state_deleted(want=None, have=have_item)
- )
- else:
- for want_item in want:
- name = want_item["name"]
- have_item = search_obj_in_list(name, have)
- if state == "merged":
- commands.extend(
- self._state_merged(want=want_item, have=have_item)
- )
- else:
- commands.extend(
- self._state_replaced(want=want_item, have=have_item)
- )
- return commands
-
- def _state_replaced(self, want, have):
- """ The command generator when state is replaced
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
- if have:
- commands.extend(self._state_deleted(want, have))
- commands.extend(self._state_merged(want, have))
- return commands
-
- def _state_overridden(self, want, have):
- """ The command generator when state is overridden
-
- :rtype: A list
- :returns: the commands necessary to migrate the current configuration
- to the desired configuration
- """
- commands = []
- for have_item in have:
- lldp_name = have_item["name"]
- lldp_in_want = search_obj_in_list(lldp_name, want)
- if not lldp_in_want:
- commands.append(
- self._compute_command(have_item["name"], remove=True)
- )
-
- for want_item in want:
- name = want_item["name"]
- lldp_in_have = search_obj_in_list(name, have)
- commands.extend(self._state_replaced(want_item, lldp_in_have))
- return commands
-
- def _state_merged(self, want, have):
- """ The command generator when state is merged
-
- :rtype: A list
- :returns: the commands necessary to merge the provided into
- the current configuration
- """
- commands = []
- if have:
- commands.extend(self._render_updates(want, have))
- else:
- commands.extend(self._render_set_commands(want))
- return commands
-
- def _state_deleted(self, want, have):
- """ The command generator when state is deleted
-
- :rtype: A list
- :returns: the commands necessary to remove the current configuration
- of the provided objects
- """
- commands = []
- if want:
- params = Lldp_interfaces.params
- for attrib in params:
- if attrib == "location":
- commands.extend(
- self._update_location(have["name"], want, have)
- )
-
- elif have:
- commands.append(self._compute_command(have["name"], remove=True))
- return commands
-
- def _render_updates(self, want, have):
- commands = []
- lldp_name = have["name"]
- commands.extend(self._configure_status(lldp_name, want, have))
- commands.extend(self._add_location(lldp_name, want, have))
-
- return commands
-
- def _render_set_commands(self, want):
- commands = []
- have = {}
- lldp_name = want["name"]
- params = Lldp_interfaces.params
-
- commands.extend(self._add_location(lldp_name, want, have))
- for attrib in params:
- value = want[attrib]
- if value:
- if attrib == "location":
- commands.extend(self._add_location(lldp_name, want, have))
- elif attrib == "enable":
- if not value:
- commands.append(
- self._compute_command(lldp_name, value="disable")
- )
- else:
- commands.append(self._compute_command(lldp_name))
-
- return commands
-
- def _configure_status(self, name, want_item, have_item):
- commands = []
- if is_dict_element_present(have_item, "enable"):
- temp_have_item = False
- else:
- temp_have_item = True
- if want_item["enable"] != temp_have_item:
- if want_item["enable"]:
- commands.append(
- self._compute_command(name, value="disable", remove=True)
- )
- else:
- commands.append(self._compute_command(name, value="disable"))
- return commands
-
- def _add_location(self, name, want_item, have_item):
- commands = []
- have_dict = {}
- have_ca = {}
- set_cmd = name + " location "
- want_location_type = want_item.get("location") or {}
- have_location_type = have_item.get("location") or {}
-
- if want_location_type["coordinate_based"]:
- want_dict = want_location_type.get("coordinate_based") or {}
- if is_dict_element_present(have_location_type, "coordinate_based"):
- have_dict = have_location_type.get("coordinate_based") or {}
- location_type = "coordinate-based"
- updates = dict_diff(have_dict, want_dict)
- for key, value in iteritems(updates):
- if value:
- commands.append(
- self._compute_command(
- set_cmd + location_type, key, str(value)
- )
- )
-
- elif want_location_type["civic_based"]:
- location_type = "civic-based"
- want_dict = want_location_type.get("civic_based") or {}
- want_ca = want_dict.get("ca_info") or []
- if is_dict_element_present(have_location_type, "civic_based"):
- have_dict = have_location_type.get("civic_based") or {}
- have_ca = have_dict.get("ca_info") or []
- if want_dict["country_code"] != have_dict["country_code"]:
- commands.append(
- self._compute_command(
- set_cmd + location_type,
- "country-code",
- str(want_dict["country_code"]),
- )
- )
- else:
- commands.append(
- self._compute_command(
- set_cmd + location_type,
- "country-code",
- str(want_dict["country_code"]),
- )
- )
- commands.extend(self._add_civic_address(name, want_ca, have_ca))
-
- elif want_location_type["elin"]:
- location_type = "elin"
- if is_dict_element_present(have_location_type, "elin"):
- if want_location_type.get("elin") != have_location_type.get(
- "elin"
- ):
- commands.append(
- self._compute_command(
- set_cmd + location_type,
- value=str(want_location_type["elin"]),
- )
- )
- else:
- commands.append(
- self._compute_command(
- set_cmd + location_type,
- value=str(want_location_type["elin"]),
- )
- )
- return commands
-
- def _update_location(self, name, want_item, have_item):
- commands = []
- del_cmd = name + " location"
- want_location_type = want_item.get("location") or {}
- have_location_type = have_item.get("location") or {}
-
- if want_location_type["coordinate_based"]:
- want_dict = want_location_type.get("coordinate_based") or {}
- if is_dict_element_present(have_location_type, "coordinate_based"):
- have_dict = have_location_type.get("coordinate_based") or {}
- location_type = "coordinate-based"
- for key, value in iteritems(have_dict):
- only_in_have = key_value_in_dict(key, value, want_dict)
- if not only_in_have:
- commands.append(
- self._compute_command(
- del_cmd + location_type, key, str(value), True
- )
- )
- else:
- commands.append(self._compute_command(del_cmd, remove=True))
-
- elif want_location_type["civic_based"]:
- want_dict = want_location_type.get("civic_based") or {}
- want_ca = want_dict.get("ca_info") or []
- if is_dict_element_present(have_location_type, "civic_based"):
- have_dict = have_location_type.get("civic_based") or {}
- have_ca = have_dict.get("ca_info")
- commands.extend(
- self._update_civic_address(name, want_ca, have_ca)
- )
- else:
- commands.append(self._compute_command(del_cmd, remove=True))
-
- else:
- if is_dict_element_present(have_location_type, "elin"):
- if want_location_type.get("elin") != have_location_type.get(
- "elin"
- ):
- commands.append(
- self._compute_command(del_cmd, remove=True)
- )
- else:
- commands.append(self._compute_command(del_cmd, remove=True))
- return commands
-
- def _add_civic_address(self, name, want, have):
- commands = []
- for item in want:
- ca_type = item["ca_type"]
- ca_value = item["ca_value"]
- obj_in_have = search_dict_tv_in_list(
- ca_type, ca_value, have, "ca_type", "ca_value"
- )
- if not obj_in_have:
- commands.append(
- self._compute_command(
- key=name + " location civic-based ca-type",
- attrib=str(ca_type) + " ca-value",
- value=ca_value,
- )
- )
- return commands
-
- def _update_civic_address(self, name, want, have):
- commands = []
- for item in have:
- ca_type = item["ca_type"]
- ca_value = item["ca_value"]
- in_want = search_dict_tv_in_list(
- ca_type, ca_value, want, "ca_type", "ca_value"
- )
- if not in_want:
- commands.append(
- self._compute_command(
- name,
- "location civic-based ca-type",
- str(ca_type),
- remove=True,
- )
- )
- return commands
-
- def _compute_command(self, key, attrib=None, value=None, remove=False):
- if remove:
- cmd = "delete service lldp interface "
- else:
- cmd = "set service lldp interface "
- cmd += key
- if attrib:
- cmd += " " + attrib
- if value:
- cmd += " '" + value + "'"
- return cmd
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/facts.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/facts.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/facts.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/facts.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,83 +0,0 @@
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The facts class for vyos
-this file validates each subset of facts and selectively
-calls the appropriate facts gathering function
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import (
- FactsBase,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.interfaces.interfaces import (
- InterfacesFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.l3_interfaces.l3_interfaces import (
- L3_interfacesFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lag_interfaces.lag_interfaces import (
- Lag_interfacesFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_global.lldp_global import (
- Lldp_globalFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.lldp_interfaces.lldp_interfaces import (
- Lldp_interfacesFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.firewall_rules.firewall_rules import (
- Firewall_rulesFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.static_routes.static_routes import (
- Static_routesFacts,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.legacy.base import (
- Default,
- Neighbors,
- Config,
-)
-
-
-FACT_LEGACY_SUBSETS = dict(default=Default, neighbors=Neighbors, config=Config)
-FACT_RESOURCE_SUBSETS = dict(
- interfaces=InterfacesFacts,
- l3_interfaces=L3_interfacesFacts,
- lag_interfaces=Lag_interfacesFacts,
- lldp_global=Lldp_globalFacts,
- lldp_interfaces=Lldp_interfacesFacts,
- static_routes=Static_routesFacts,
- firewall_rules=Firewall_rulesFacts,
-)
-
-
-class Facts(FactsBase):
- """ The fact class for vyos
- """
-
- VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
- VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
-
- def __init__(self, module):
- super(Facts, self).__init__(module)
-
- def get_facts(
- self, legacy_facts_type=None, resource_facts_type=None, data=None
- ):
- """ Collect the facts for vyos
- :param legacy_facts_type: List of legacy facts types
- :param resource_facts_type: List of resource fact types
- :param data: previously collected conf
- :rtype: dict
- :return: the facts gathered
- """
- if self.VALID_RESOURCE_SUBSETS:
- self.get_network_resources_facts(
- FACT_RESOURCE_SUBSETS, resource_facts_type, data
- )
- if self.VALID_LEGACY_GATHER_SUBSETS:
- self.get_network_legacy_facts(
- FACT_LEGACY_SUBSETS, legacy_facts_type
- )
- return self.ansible_facts, self._warnings
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/firewall_rules/firewall_rules.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,380 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos firewall_rules fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-from re import findall, search, M
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.firewall_rules.firewall_rules import (
- Firewall_rulesArgs,
-)
-
-
-class Firewall_rulesFacts(object):
- """ The vyos firewall_rules fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = Firewall_rulesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def get_device_data(self, connection):
- return connection.get_config()
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for firewall_rules
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- # typically data is populated from the current device configuration
- # data = connection.get('show running-config | section ^interface')
- # using mock data instead
- data = self.get_device_data(connection)
- # split the config into instances of the resource
- objs = []
- v6_rules = findall(
- r"^set firewall ipv6-name (?:\'*)(\S+)(?:\'*)", data, M
- )
- v4_rules = findall(r"^set firewall name (?:\'*)(\S+)(?:\'*)", data, M)
- if v6_rules:
- config = self.get_rules(data, v6_rules, type="ipv6")
- if config:
- config = utils.remove_empties(config)
- objs.append(config)
- if v4_rules:
- config = self.get_rules(data, v4_rules, type="ipv4")
- if config:
- config = utils.remove_empties(config)
- objs.append(config)
-
- ansible_facts["ansible_network_resources"].pop("firewall_rules", None)
- facts = {}
- if objs:
- facts["firewall_rules"] = []
- params = utils.validate_config(
- self.argument_spec, {"config": objs}
- )
- for cfg in params["config"]:
- facts["firewall_rules"].append(utils.remove_empties(cfg))
-
- ansible_facts["ansible_network_resources"].update(facts)
- return ansible_facts
-
- def get_rules(self, data, rules, type):
- """
- This function performs following:
- - Form regex to fetch 'rule-sets' specific config from data.
- - Form the rule-set list based on ip address.
- :param data: configuration.
- :param rules: list of rule-sets.
- :param type: ip address type.
- :return: generated rule-sets configuration.
- """
- r_v4 = []
- r_v6 = []
- for r in set(rules):
- rule_regex = r" %s .+$" % r.strip("'")
- cfg = findall(rule_regex, data, M)
- fr = self.render_config(cfg, r.strip("'"))
- fr["name"] = r.strip("'")
- if type == "ipv6":
- r_v6.append(fr)
- else:
- r_v4.append(fr)
- if r_v4:
- config = {"afi": "ipv4", "rule_sets": r_v4}
- if r_v6:
- config = {"afi": "ipv6", "rule_sets": r_v6}
- return config
-
- def render_config(self, conf, match):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- conf = "\n".join(filter(lambda x: x, conf))
- a_lst = ["description", "default_action", "enable_default_log"]
- config = self.parse_attr(conf, a_lst, match)
- if not config:
- config = {}
- config["rules"] = self.parse_rules_lst(conf)
- return config
-
- def parse_rules_lst(self, conf):
- """
- This function forms the regex to fetch the 'rules' with in
- 'rule-sets'
- :param conf: configuration data.
- :return: generated rule list configuration.
- """
- r_lst = []
- rules = findall(r"rule (?:\'*)(\d+)(?:\'*)", conf, M)
- if rules:
- rules_lst = []
- for r in set(rules):
- r_regex = r" %s .+$" % r
- cfg = "\n".join(findall(r_regex, conf, M))
- obj = self.parse_rules(cfg)
- obj["number"] = int(r)
- if obj:
- rules_lst.append(obj)
- r_lst = sorted(rules_lst, key=lambda i: i["number"])
- return r_lst
-
- def parse_rules(self, conf):
- """
- This function triggers the parsing of 'rule' attributes.
- a_lst is a list having rule attributes which doesn't
- have further sub attributes.
- :param conf: configuration
- :return: generated rule configuration dictionary.
- """
- a_lst = [
- "ipsec",
- "action",
- "protocol",
- "fragment",
- "disabled",
- "description",
- ]
- rule = self.parse_attr(conf, a_lst)
- r_sub = {
- "p2p": self.parse_p2p(conf),
- "tcp": self.parse_tcp(conf, "tcp"),
- "icmp": self.parse_icmp(conf, "icmp"),
- "time": self.parse_time(conf, "time"),
- "limit": self.parse_limit(conf, "limit"),
- "state": self.parse_state(conf, "state"),
- "recent": self.parse_recent(conf, "recent"),
- "source": self.parse_src_or_dest(conf, "source"),
- "destination": self.parse_src_or_dest(conf, "destination"),
- }
- rule.update(r_sub)
- return rule
-
- def parse_p2p(self, conf):
- """
- This function forms the regex to fetch the 'p2p' with in
- 'rules'
- :param conf: configuration data.
- :return: generated rule list configuration.
- """
- a_lst = []
- applications = findall(r"p2p (?:\'*)(\d+)(?:\'*)", conf, M)
- if applications:
- app_lst = []
- for r in set(applications):
- obj = {"application": r.strip("'")}
- app_lst.append(obj)
- a_lst = sorted(app_lst, key=lambda i: i["application"])
- return a_lst
-
- def parse_src_or_dest(self, conf, attrib=None):
- """
- This function triggers the parsing of 'source or
- destination' attributes.
- :param conf: configuration.
- :param attrib:'source/destination'.
- :return:generated source/destination configuration dictionary.
- """
- a_lst = ["port", "address", "mac_address"]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- cfg_dict["group"] = self.parse_group(conf, attrib + " group")
- return cfg_dict
-
- def parse_recent(self, conf, attrib=None):
- """
- This function triggers the parsing of 'recent' attributes
- :param conf: configuration.
- :param attrib: 'recent'.
- :return: generated config dictionary.
- """
- a_lst = ["time", "count"]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- return cfg_dict
-
- def parse_tcp(self, conf, attrib=None):
- """
- This function triggers the parsing of 'tcp' attributes.
- :param conf: configuration.
- :param attrib: 'tcp'.
- :return: generated config dictionary.
- """
- cfg_dict = self.parse_attr(conf, ["flags"], match=attrib)
- return cfg_dict
-
- def parse_time(self, conf, attrib=None):
- """
- This function triggers the parsing of 'time' attributes.
- :param conf: configuration.
- :param attrib: 'time'.
- :return: generated config dictionary.
- """
- a_lst = [
- "stopdate",
- "stoptime",
- "weekdays",
- "monthdays",
- "startdate",
- "starttime",
- ]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- return cfg_dict
-
- def parse_state(self, conf, attrib=None):
- """
- This function triggers the parsing of 'state' attributes.
- :param conf: configuration
- :param attrib: 'state'.
- :return: generated config dictionary.
- """
- a_lst = ["new", "invalid", "related", "established"]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- return cfg_dict
-
- def parse_group(self, conf, attrib=None):
- """
- This function triggers the parsing of 'group' attributes.
- :param conf: configuration.
- :param attrib: 'group'.
- :return: generated config dictionary.
- """
- a_lst = ["port_group", "address_group", "network_group"]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- return cfg_dict
-
- def parse_icmp(self, conf, attrib=None):
- """
- This function triggers the parsing of 'icmp' attributes.
- :param conf: configuration to be parsed.
- :param attrib: 'icmp'.
- :return: generated config dictionary.
- """
- a_lst = ["code", "type", "type_name"]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- return cfg_dict
-
- def parse_limit(self, conf, attrib=None):
- """
- This function triggers the parsing of 'limit' attributes.
- :param conf: configuration to be parsed.
- :param attrib: 'limit'
- :return: generated config dictionary.
- """
- cfg_dict = self.parse_attr(conf, ["burst"], match=attrib)
- cfg_dict["rate"] = self.parse_rate(conf, "rate")
- return cfg_dict
-
- def parse_rate(self, conf, attrib=None):
- """
- This function triggers the parsing of 'rate' attributes.
- :param conf: configuration.
- :param attrib: 'rate'
- :return: generated config dictionary.
- """
- a_lst = ["unit", "number"]
- cfg_dict = self.parse_attr(conf, a_lst, match=attrib)
- return cfg_dict
-
- def parse_attr(self, conf, attr_list, match=None):
- """
- This function peforms the following:
- - Form the regex to fetch the required attribute config.
- - Type cast the output in desired format.
- :param conf: configuration.
- :param attr_list: list of attributes.
- :param match: parent node/attribute name.
- :return: generated config dictionary.
- """
- config = {}
- for attrib in attr_list:
- regex = self.map_regex(attrib)
- if match:
- regex = match + " " + regex
- if conf:
- if self.is_bool(attrib):
- out = conf.find(attrib.replace("_", "-"))
-
- dis = conf.find(attrib.replace("_", "-") + " 'disable'")
- if out >= 1:
- if dis >= 1:
- config[attrib] = False
- else:
- config[attrib] = True
- else:
- out = search(r"^.*" + regex + " (.+)", conf, M)
- if out:
- val = out.group(1).strip("'")
- if self.is_num(attrib):
- val = int(val)
- config[attrib] = val
- return config
-
- def map_regex(self, attrib):
- """
- - This function construct the regex string.
- - replace the underscore with hyphen.
- :param attrib: attribute
- :return: regex string
- """
- regex = attrib.replace("_", "-")
- if attrib == "disabled":
- regex = "disable"
- return regex
-
- def is_bool(self, attrib):
- """
- This function looks for the attribute in predefined bool type set.
- :param attrib: attribute.
- :return: True/False
- """
- bool_set = (
- "new",
- "invalid",
- "related",
- "disabled",
- "established",
- "enable_default_log",
- )
- return True if attrib in bool_set else False
-
- def is_num(self, attrib):
- """
- This function looks for the attribute in predefined integer type set.
- :param attrib: attribute.
- :return: True/false.
- """
- num_set = ("time", "code", "type", "count", "burst", "number")
- return True if attrib in num_set else False
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,134 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-from re import findall, M
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.interfaces.interfaces import (
- InterfacesArgs,
-)
-
-
-class InterfacesFacts(object):
- """ The vyos interfaces fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = InterfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get_config(flags=["| grep interfaces"])
-
- objs = []
- interface_names = findall(
- r"^set interfaces (?:ethernet|bonding|vti|loopback|vxlan) (?:\'*)(\S+)(?:\'*)",
- data,
- M,
- )
- if interface_names:
- for interface in set(interface_names):
- intf_regex = r" %s .+$" % interface.strip("'")
- cfg = findall(intf_regex, data, M)
- obj = self.render_config(cfg)
- obj["name"] = interface.strip("'")
- if obj:
- objs.append(obj)
- facts = {}
- if objs:
- facts["interfaces"] = []
- params = utils.validate_config(
- self.argument_spec, {"config": objs}
- )
- for cfg in params["config"]:
- facts["interfaces"].append(utils.remove_empties(cfg))
-
- ansible_facts["ansible_network_resources"].update(facts)
- return ansible_facts
-
- def render_config(self, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- vif_conf = "\n".join(filter(lambda x: ("vif" in x), conf))
- eth_conf = "\n".join(filter(lambda x: ("vif" not in x), conf))
- config = self.parse_attribs(
- ["description", "speed", "mtu", "duplex"], eth_conf
- )
- config["vifs"] = self.parse_vifs(vif_conf)
-
- return utils.remove_empties(config)
-
- def parse_vifs(self, conf):
- vif_names = findall(r"vif (?:\'*)(\d+)(?:\'*)", conf, M)
- vifs_list = None
-
- if vif_names:
- vifs_list = []
- for vif in set(vif_names):
- vif_regex = r" %s .+$" % vif
- cfg = "\n".join(findall(vif_regex, conf, M))
- obj = self.parse_attribs(["description", "mtu"], cfg)
- obj["vlan_id"] = int(vif)
- if obj:
- vifs_list.append(obj)
- vifs_list = sorted(vifs_list, key=lambda i: i["vlan_id"])
-
- return vifs_list
-
- def parse_attribs(self, attribs, conf):
- config = {}
- for item in attribs:
- value = utils.parse_conf_arg(conf, item)
- if value and item == "mtu":
- config[item] = int(value.strip("'"))
- elif value:
- config[item] = value.strip("'")
- else:
- config[item] = None
- if "disable" in conf:
- config["enabled"] = False
- else:
- config["enabled"] = True
-
- return utils.remove_empties(config)
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,143 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos l3_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-import re
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible.module_utils.six import iteritems
-from ansible_collections.ansible.netcommon.plugins.module_utils.compat import (
- ipaddress,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.l3_interfaces.l3_interfaces import (
- L3_interfacesArgs,
-)
-
-
-class L3_interfacesFacts(object):
- """ The vyos l3_interfaces fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = L3_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for l3_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get_config()
-
- # operate on a collection of resource x
- objs = []
- interface_names = re.findall(
- r"set interfaces (?:ethernet|bonding|vti|vxlan) (?:\'*)(\S+)(?:\'*)",
- data,
- re.M,
- )
- if interface_names:
- for interface in set(interface_names):
- intf_regex = r" %s .+$" % interface
- cfg = re.findall(intf_regex, data, re.M)
- obj = self.render_config(cfg)
- obj["name"] = interface.strip("'")
- if obj:
- objs.append(obj)
-
- ansible_facts["ansible_network_resources"].pop("l3_interfaces", None)
- facts = {}
- if objs:
- facts["l3_interfaces"] = []
- params = utils.validate_config(
- self.argument_spec, {"config": objs}
- )
- for cfg in params["config"]:
- facts["l3_interfaces"].append(utils.remove_empties(cfg))
-
- ansible_facts["ansible_network_resources"].update(facts)
- return ansible_facts
-
- def render_config(self, conf):
- """
- Render config as dictionary structure and delete keys from spec for null values
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- vif_conf = "\n".join(filter(lambda x: ("vif" in x), conf))
- eth_conf = "\n".join(filter(lambda x: ("vif" not in x), conf))
- config = self.parse_attribs(eth_conf)
- config["vifs"] = self.parse_vifs(vif_conf)
-
- return utils.remove_empties(config)
-
- def parse_vifs(self, conf):
- vif_names = re.findall(r"vif (\d+)", conf, re.M)
- vifs_list = None
- if vif_names:
- vifs_list = []
- for vif in set(vif_names):
- vif_regex = r" %s .+$" % vif
- cfg = "\n".join(re.findall(vif_regex, conf, re.M))
- obj = self.parse_attribs(cfg)
- obj["vlan_id"] = vif
- if obj:
- vifs_list.append(obj)
-
- return vifs_list
-
- def parse_attribs(self, conf):
- config = {}
- ipaddrs = re.findall(r"address (\S+)", conf, re.M)
- config["ipv4"] = []
- config["ipv6"] = []
-
- for item in ipaddrs:
- item = item.strip("'")
- if item == "dhcp":
- config["ipv4"].append({"address": item})
- elif item == "dhcpv6":
- config["ipv6"].append({"address": item})
- else:
- ip_version = ipaddress.ip_address(item.split("/")[0]).version
- if ip_version == 4:
- config["ipv4"].append({"address": item})
- else:
- config["ipv6"].append({"address": item})
-
- for key, value in iteritems(config):
- if value == []:
- config[key] = None
-
- return utils.remove_empties(config)
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,152 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos lag_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-from re import findall, search, M
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lag_interfaces.lag_interfaces import (
- Lag_interfacesArgs,
-)
-
-
-class Lag_interfacesFacts(object):
- """ The vyos lag_interfaces fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = Lag_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lag_interfaces
- :param module: the module instance
- :param connection: the device connection
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get_config()
-
- objs = []
- lag_names = findall(r"^set interfaces bonding (\S+)", data, M)
- if lag_names:
- for lag in set(lag_names):
- lag_regex = r" %s .+$" % lag
- cfg = findall(lag_regex, data, M)
- obj = self.render_config(cfg)
-
- output = connection.run_commands(
- ["show interfaces bonding " + lag + " slaves"]
- )
- lines = output[0].splitlines()
- members = []
- member = {}
- if len(lines) > 1:
- for line in lines[2:]:
- splitted_line = line.split()
-
- if len(splitted_line) > 1:
- member["member"] = splitted_line[0]
- members.append(member)
- else:
- members = []
- member = {}
- obj["name"] = lag.strip("'")
- if members:
- obj["members"] = members
-
- if obj:
- objs.append(obj)
-
- facts = {}
- if objs:
- facts["lag_interfaces"] = []
- params = utils.validate_config(
- self.argument_spec, {"config": objs}
- )
- for cfg in params["config"]:
- facts["lag_interfaces"].append(utils.remove_empties(cfg))
-
- ansible_facts["ansible_network_resources"].update(facts)
- return ansible_facts
-
- def render_config(self, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- arp_monitor_conf = "\n".join(
- filter(lambda x: ("arp-monitor" in x), conf)
- )
- hash_policy_conf = "\n".join(
- filter(lambda x: ("hash-policy" in x), conf)
- )
- lag_conf = "\n".join(filter(lambda x: ("bond" in x), conf))
- config = self.parse_attribs(["mode", "primary"], lag_conf)
- config["arp_monitor"] = self.parse_arp_monitor(arp_monitor_conf)
- config["hash_policy"] = self.parse_hash_policy(hash_policy_conf)
-
- return utils.remove_empties(config)
-
- def parse_attribs(self, attribs, conf):
- config = {}
- for item in attribs:
- value = utils.parse_conf_arg(conf, item)
- if value:
- config[item] = value.strip("'")
- else:
- config[item] = None
- return utils.remove_empties(config)
-
- def parse_arp_monitor(self, conf):
- arp_monitor = None
- if conf:
- arp_monitor = {}
- target_list = []
- interval = search(r"^.*arp-monitor interval (.+)", conf, M)
- targets = findall(r"^.*arp-monitor target '(.+)'", conf, M)
- if targets:
- for target in targets:
- target_list.append(target)
- arp_monitor["target"] = target_list
- if interval:
- value = interval.group(1).strip("'")
- arp_monitor["interval"] = int(value)
- return arp_monitor
-
- def parse_hash_policy(self, conf):
- hash_policy = None
- if conf:
- hash_policy = search(r"^.*hash-policy (.+)", conf, M)
- hash_policy = hash_policy.group(1).strip("'")
- return hash_policy
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/legacy/base.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/legacy/base.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/legacy/base.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/legacy/base.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,162 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The VyOS interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-import platform
-import re
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import (
- run_commands,
- get_capabilities,
-)
-
-
-class LegacyFactsBase(object):
-
- COMMANDS = frozenset()
-
- def __init__(self, module):
- self.module = module
- self.facts = dict()
- self.warnings = list()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, list(self.COMMANDS))
-
-
-class Default(LegacyFactsBase):
-
- COMMANDS = [
- "show version",
- ]
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- self.facts["serialnum"] = self.parse_serialnum(data)
- self.facts.update(self.platform_facts())
-
- def parse_serialnum(self, data):
- match = re.search(r"HW S/N:\s+(\S+)", data)
- if match:
- return match.group(1)
-
- def platform_facts(self):
- platform_facts = {}
-
- resp = get_capabilities(self.module)
- device_info = resp["device_info"]
-
- platform_facts["system"] = device_info["network_os"]
-
- for item in ("model", "image", "version", "platform", "hostname"):
- val = device_info.get("network_os_%s" % item)
- if val:
- platform_facts[item] = val
-
- platform_facts["api"] = resp["network_api"]
- platform_facts["python_version"] = platform.python_version()
-
- return platform_facts
-
-
-class Config(LegacyFactsBase):
-
- COMMANDS = [
- "show configuration commands",
- "show system commit",
- ]
-
- def populate(self):
- super(Config, self).populate()
-
- self.facts["config"] = self.responses
-
- commits = self.responses[1]
- entries = list()
- entry = None
-
- for line in commits.split("\n"):
- match = re.match(r"(\d+)\s+(.+)by(.+)via(.+)", line)
- if match:
- if entry:
- entries.append(entry)
-
- entry = dict(
- revision=match.group(1),
- datetime=match.group(2),
- by=str(match.group(3)).strip(),
- via=str(match.group(4)).strip(),
- comment=None,
- )
- else:
- entry["comment"] = line.strip()
-
- self.facts["commits"] = entries
-
-
-class Neighbors(LegacyFactsBase):
-
- COMMANDS = [
- "show lldp neighbors",
- "show lldp neighbors detail",
- ]
-
- def populate(self):
- super(Neighbors, self).populate()
-
- all_neighbors = self.responses[0]
- if "LLDP not configured" not in all_neighbors:
- neighbors = self.parse(self.responses[1])
- self.facts["neighbors"] = self.parse_neighbors(neighbors)
-
- def parse(self, data):
- parsed = list()
- values = None
- for line in data.split("\n"):
- if not line:
- continue
- elif line[0] == " ":
- values += "\n%s" % line
- elif line.startswith("Interface"):
- if values:
- parsed.append(values)
- values = line
- if values:
- parsed.append(values)
- return parsed
-
- def parse_neighbors(self, data):
- facts = dict()
- for item in data:
- interface = self.parse_interface(item)
- host = self.parse_host(item)
- port = self.parse_port(item)
- if interface not in facts:
- facts[interface] = list()
- facts[interface].append(dict(host=host, port=port))
- return facts
-
- def parse_interface(self, data):
- match = re.search(r"^Interface:\s+(\S+),", data)
- return match.group(1)
-
- def parse_host(self, data):
- match = re.search(r"SysName:\s+(.+)$", data, re.M)
- if match:
- return match.group(1)
-
- def parse_port(self, data):
- match = re.search(r"PortDescr:\s+(.+)$", data, re.M)
- if match:
- return match.group(1)
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,116 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos lldp_global fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-from re import findall, M
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_global.lldp_global import (
- Lldp_globalArgs,
-)
-
-
-class Lldp_globalFacts(object):
- """ The vyos lldp_global fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = Lldp_globalArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_global
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get_config()
-
- objs = {}
- lldp_output = findall(r"^set service lldp (\S+)", data, M)
- if lldp_output:
- for item in set(lldp_output):
- lldp_regex = r" %s .+$" % item
- cfg = findall(lldp_regex, data, M)
- obj = self.render_config(cfg)
- if obj:
- objs.update(obj)
- lldp_service = findall(r"^set service (lldp)?('lldp')", data, M)
- if lldp_service or lldp_output:
- lldp_obj = {}
- lldp_obj["enable"] = True
- objs.update(lldp_obj)
-
- facts = {}
- params = utils.validate_config(self.argument_spec, {"config": objs})
- facts["lldp_global"] = utils.remove_empties(params["config"])
-
- ansible_facts["ansible_network_resources"].update(facts)
-
- return ansible_facts
-
- def render_config(self, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- protocol_conf = "\n".join(
- filter(lambda x: ("legacy-protocols" in x), conf)
- )
- att_conf = "\n".join(
- filter(lambda x: ("legacy-protocols" not in x), conf)
- )
- config = self.parse_attribs(["snmp", "address"], att_conf)
- config["legacy_protocols"] = self.parse_protocols(protocol_conf)
- return utils.remove_empties(config)
-
- def parse_protocols(self, conf):
- protocol_support = None
- if conf:
- protocols = findall(r"^.*legacy-protocols (.+)", conf, M)
- if protocols:
- protocol_support = []
- for protocol in protocols:
- protocol_support.append(protocol.strip("'"))
- return protocol_support
-
- def parse_attribs(self, attribs, conf):
- config = {}
- for item in attribs:
- value = utils.parse_conf_arg(conf, item)
- if value:
- config[item] = value.strip("'")
- else:
- config[item] = None
- return utils.remove_empties(config)
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,155 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos lldp_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-
-
-from re import findall, search, M
-from copy import deepcopy
-
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_interfaces.lldp_interfaces import (
- Lldp_interfacesArgs,
-)
-
-
-class Lldp_interfacesFacts(object):
- """ The vyos lldp_interfaces fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = Lldp_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get_config()
-
- objs = []
- lldp_names = findall(r"^set service lldp interface (\S+)", data, M)
- if lldp_names:
- for lldp in set(lldp_names):
- lldp_regex = r" %s .+$" % lldp
- cfg = findall(lldp_regex, data, M)
- obj = self.render_config(cfg)
- obj["name"] = lldp.strip("'")
- if obj:
- objs.append(obj)
- facts = {}
- if objs:
- facts["lldp_interfaces"] = objs
- ansible_facts["ansible_network_resources"].update(facts)
-
- ansible_facts["ansible_network_resources"].update(facts)
- return ansible_facts
-
- def render_config(self, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- config = {}
- location = {}
-
- civic_conf = "\n".join(filter(lambda x: ("civic-based" in x), conf))
- elin_conf = "\n".join(filter(lambda x: ("elin" in x), conf))
- coordinate_conf = "\n".join(
- filter(lambda x: ("coordinate-based" in x), conf)
- )
- disable = "\n".join(filter(lambda x: ("disable" in x), conf))
-
- coordinate_based_conf = self.parse_attribs(
- ["altitude", "datum", "longitude", "latitude"], coordinate_conf
- )
- elin_based_conf = self.parse_lldp_elin_based(elin_conf)
- civic_based_conf = self.parse_lldp_civic_based(civic_conf)
- if disable:
- config["enable"] = False
- if coordinate_conf:
- location["coordinate_based"] = coordinate_based_conf
- config["location"] = location
- elif civic_based_conf:
- location["civic_based"] = civic_based_conf
- config["location"] = location
- elif elin_conf:
- location["elin"] = elin_based_conf
- config["location"] = location
-
- return utils.remove_empties(config)
-
- def parse_attribs(self, attribs, conf):
- config = {}
- for item in attribs:
- value = utils.parse_conf_arg(conf, item)
- if value:
- value = value.strip("'")
- if item == "altitude":
- value = int(value)
- config[item] = value
- else:
- config[item] = None
- return utils.remove_empties(config)
-
- def parse_lldp_civic_based(self, conf):
- civic_based = None
- if conf:
- civic_info_list = []
- civic_add_list = findall(r"^.*civic-based ca-type (.+)", conf, M)
- if civic_add_list:
- for civic_add in civic_add_list:
- ca = civic_add.split(" ")
- c_add = {}
- c_add["ca_type"] = int(ca[0].strip("'"))
- c_add["ca_value"] = ca[2].strip("'")
- civic_info_list.append(c_add)
-
- country_code = search(
- r"^.*civic-based country-code (.+)", conf, M
- )
- civic_based = {}
- civic_based["ca_info"] = civic_info_list
- civic_based["country_code"] = country_code.group(1).strip("'")
- return civic_based
-
- def parse_lldp_elin_based(self, conf):
- elin_based = None
- if conf:
- e_num = search(r"^.* elin (.+)", conf, M)
- elin_based = e_num.group(1).strip("'")
-
- return elin_based
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/facts/static_routes/static_routes.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,181 +0,0 @@
-#
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-"""
-The vyos static_routes fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-from re import findall, search, M
-from copy import deepcopy
-from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
- utils,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.static_routes.static_routes import (
- Static_routesArgs,
-)
-from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import (
- get_route_type,
-)
-
-
-class Static_routesFacts(object):
- """ The vyos static_routes fact class
- """
-
- def __init__(self, module, subspec="config", options="options"):
- self._module = module
- self.argument_spec = Static_routesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def get_device_data(self, connection):
- return connection.get_config()
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for static_routes
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = self.get_device_data(connection)
- # typically data is populated from the current device configuration
- # data = connection.get('show running-config | section ^interface')
- # using mock data instead
- objs = []
- r_v4 = []
- r_v6 = []
- af = []
- static_routes = findall(
- r"set protocols static route(6)? (\S+)", data, M
- )
- if static_routes:
- for route in set(static_routes):
- route_regex = r" %s .+$" % route[1]
- cfg = findall(route_regex, data, M)
- sr = self.render_config(cfg)
- sr["dest"] = route[1].strip("'")
- afi = self.get_afi(sr["dest"])
- if afi == "ipv4":
- r_v4.append(sr)
- else:
- r_v6.append(sr)
- if r_v4:
- afi_v4 = {"afi": "ipv4", "routes": r_v4}
- af.append(afi_v4)
- if r_v6:
- afi_v6 = {"afi": "ipv6", "routes": r_v6}
- af.append(afi_v6)
- config = {"address_families": af}
- if config:
- objs.append(config)
-
- ansible_facts["ansible_network_resources"].pop("static_routes", None)
- facts = {}
- if objs:
- facts["static_routes"] = []
- params = utils.validate_config(
- self.argument_spec, {"config": objs}
- )
- for cfg in params["config"]:
- facts["static_routes"].append(utils.remove_empties(cfg))
-
- ansible_facts["ansible_network_resources"].update(facts)
- return ansible_facts
-
- def render_config(self, conf):
- """
- Render config as dictionary structure and delete keys
- from spec for null values
-
- :param spec: The facts tree, generated from the argspec
- :param conf: The configuration
- :rtype: dictionary
- :returns: The generated config
- """
- next_hops_conf = "\n".join(filter(lambda x: ("next-hop" in x), conf))
- blackhole_conf = "\n".join(filter(lambda x: ("blackhole" in x), conf))
- routes_dict = {
- "blackhole_config": self.parse_blackhole(blackhole_conf),
- "next_hops": self.parse_next_hop(next_hops_conf),
- }
- return routes_dict
-
- def parse_blackhole(self, conf):
- blackhole = None
- if conf:
- distance = search(r"^.*blackhole distance (.\S+)", conf, M)
- bh = conf.find("blackhole")
- if distance is not None:
- blackhole = {}
- value = distance.group(1).strip("'")
- blackhole["distance"] = int(value)
- elif bh:
- blackhole = {}
- blackhole["type"] = "blackhole"
- return blackhole
-
- def get_afi(self, address):
- route_type = get_route_type(address)
- if route_type == "route":
- return "ipv4"
- elif route_type == "route6":
- return "ipv6"
-
- def parse_next_hop(self, conf):
- nh_list = None
- if conf:
- nh_list = []
- hop_list = findall(r"^.*next-hop (.+)", conf, M)
- if hop_list:
- for hop in hop_list:
- distance = search(r"^.*distance (.\S+)", hop, M)
- interface = search(r"^.*interface (.\S+)", hop, M)
-
- dis = hop.find("disable")
- hop_info = hop.split(" ")
- nh_info = {
- "forward_router_address": hop_info[0].strip("'")
- }
- if interface:
- nh_info["interface"] = interface.group(1).strip("'")
- if distance:
- value = distance.group(1).strip("'")
- nh_info["admin_distance"] = int(value)
- elif dis >= 1:
- nh_info["enabled"] = False
- for element in nh_list:
- if (
- element["forward_router_address"]
- == nh_info["forward_router_address"]
- ):
- if "interface" in nh_info.keys():
- element["interface"] = nh_info["interface"]
- if "admin_distance" in nh_info.keys():
- element["admin_distance"] = nh_info[
- "admin_distance"
- ]
- if "enabled" in nh_info.keys():
- element["enabled"] = nh_info["enabled"]
- nh_info = None
- if nh_info is not None:
- nh_list.append(nh_info)
- return nh_list
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/utils/utils.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/utils/utils.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/utils/utils.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/utils/utils.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,231 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright 2019 Red Hat
-# GNU General Public License v3.0+
-# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# utils
-from __future__ import absolute_import, division, print_function
-
-__metaclass__ = type
-from ansible.module_utils.six import iteritems
-from ansible_collections.ansible.netcommon.plugins.module_utils.compat import (
- ipaddress,
-)
-
-
-def search_obj_in_list(name, lst, key="name"):
- for item in lst:
- if item[key] == name:
- return item
- return None
-
-
-def get_interface_type(interface):
- """Gets the type of interface
- """
- if interface.startswith("eth"):
- return "ethernet"
- elif interface.startswith("bond"):
- return "bonding"
- elif interface.startswith("vti"):
- return "vti"
- elif interface.startswith("lo"):
- return "loopback"
-
-
-def dict_delete(base, comparable):
- """
- This function generates a dict containing key, value pairs for keys
- that are present in the `base` dict but not present in the `comparable`
- dict.
-
- :param base: dict object to base the diff on
- :param comparable: dict object to compare against base
- :returns: new dict object with key, value pairs that needs to be deleted.
-
- """
- to_delete = dict()
-
- for key in base:
- if isinstance(base[key], dict):
- sub_diff = dict_delete(base[key], comparable.get(key, {}))
- if sub_diff:
- to_delete[key] = sub_diff
- else:
- if key not in comparable:
- to_delete[key] = base[key]
-
- return to_delete
-
-
-def diff_list_of_dicts(want, have):
- diff = []
-
- set_w = set(tuple(d.items()) for d in want)
- set_h = set(tuple(d.items()) for d in have)
- difference = set_w.difference(set_h)
-
- for element in difference:
- diff.append(dict((x, y) for x, y in element))
-
- return diff
-
-
-def get_lst_diff_for_dicts(want, have, lst):
- """
- This function generates a list containing values
- that are only in want and not in list in have dict
- :param want: dict object to want
- :param have: dict object to have
- :param lst: list the diff on
- :return: new list object with values which are only in want.
- """
- if not have:
- diff = want.get(lst) or []
-
- else:
- want_elements = want.get(lst) or {}
- have_elements = have.get(lst) or {}
- diff = list_diff_want_only(want_elements, have_elements)
- return diff
-
-
-def get_lst_same_for_dicts(want, have, lst):
- """
- This function generates a list containing values
- that are common for list in want and list in have dict
- :param want: dict object to want
- :param have: dict object to have
- :param lst: list the comparison on
- :return: new list object with values which are common in want and have.
- """
- diff = None
- if want and have:
- want_list = want.get(lst) or {}
- have_list = have.get(lst) or {}
- diff = [
- i
- for i in want_list and have_list
- if i in have_list and i in want_list
- ]
- return diff
-
-
-def list_diff_have_only(want_list, have_list):
- """
- This function generated the list containing values
- that are only in have list.
- :param want_list:
- :param have_list:
- :return: new list with values which are only in have list
- """
- if have_list and not want_list:
- diff = have_list
- elif not have_list:
- diff = None
- else:
- diff = [
- i
- for i in have_list + want_list
- if i in have_list and i not in want_list
- ]
- return diff
-
-
-def list_diff_want_only(want_list, have_list):
- """
- This function generated the list containing values
- that are only in want list.
- :param want_list:
- :param have_list:
- :return: new list with values which are only in want list
- """
- if have_list and not want_list:
- diff = None
- elif not have_list:
- diff = want_list
- else:
- diff = [
- i
- for i in have_list + want_list
- if i in want_list and i not in have_list
- ]
- return diff
-
-
-def search_dict_tv_in_list(d_val1, d_val2, lst, key1, key2):
- """
- This function return the dict object if it exist in list.
- :param d_val1:
- :param d_val2:
- :param lst:
- :param key1:
- :param key2:
- :return:
- """
- obj = next(
- (
- item
- for item in lst
- if item[key1] == d_val1 and item[key2] == d_val2
- ),
- None,
- )
- if obj:
- return obj
- else:
- return None
-
-
-def key_value_in_dict(have_key, have_value, want_dict):
- """
- This function checks whether the key and values exist in dict
- :param have_key:
- :param have_value:
- :param want_dict:
- :return:
- """
- for key, value in iteritems(want_dict):
- if key == have_key and value == have_value:
- return True
- return False
-
-
-def is_dict_element_present(dict, key):
- """
- This function checks whether the key is present in dict.
- :param dict:
- :param key:
- :return:
- """
- for item in dict:
- if item == key:
- return True
- return False
-
-
-def get_ip_address_version(address):
- """
- This function returns the version of IP address
- :param address: IP address
- :return:
- """
- try:
- address = unicode(address)
- except NameError:
- address = str(address)
- version = ipaddress.ip_address(address.split("/")[0]).version
- return version
-
-
-def get_route_type(address):
- """
- This function returns the route type based on IP address
- :param address:
- :return:
- """
- version = get_ip_address_version(address)
- if version == 6:
- return "route6"
- elif version == 4:
- return "route"
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/module_utils/network/vyos/vyos.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,124 +0,0 @@
-# This code is part of Ansible, but is an independent component.
-# This particular file snippet, and this file snippet only, is BSD licensed.
-# Modules you write using this snippet, which is embedded dynamically by Ansible
-# still belong to the author of the module, and may assign their own license
-# to the complete work.
-#
-# (c) 2016 Red Hat Inc.
-#
-# Redistribution and use in source and binary forms, with or without modification,
-# are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-import json
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible.module_utils.connection import Connection, ConnectionError
-
-_DEVICE_CONFIGS = {}
-
-vyos_provider_spec = {
- "host": dict(),
- "port": dict(type="int"),
- "username": dict(fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"])),
- "password": dict(
- fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]), no_log=True
- ),
- "ssh_keyfile": dict(
- fallback=(env_fallback, ["ANSIBLE_NET_SSH_KEYFILE"]), type="path"
- ),
- "timeout": dict(type="int"),
-}
-vyos_argument_spec = {
- "provider": dict(
- type="dict", options=vyos_provider_spec, removed_in_version=2.14
- ),
-}
-
-
-def get_provider_argspec():
- return vyos_provider_spec
-
-
-def get_connection(module):
- if hasattr(module, "_vyos_connection"):
- return module._vyos_connection
-
- capabilities = get_capabilities(module)
- network_api = capabilities.get("network_api")
- if network_api == "cliconf":
- module._vyos_connection = Connection(module._socket_path)
- else:
- module.fail_json(msg="Invalid connection type %s" % network_api)
-
- return module._vyos_connection
-
-
-def get_capabilities(module):
- if hasattr(module, "_vyos_capabilities"):
- return module._vyos_capabilities
-
- try:
- capabilities = Connection(module._socket_path).get_capabilities()
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
-
- module._vyos_capabilities = json.loads(capabilities)
- return module._vyos_capabilities
-
-
-def get_config(module, flags=None, format=None):
- flags = [] if flags is None else flags
- global _DEVICE_CONFIGS
-
- if _DEVICE_CONFIGS != {}:
- return _DEVICE_CONFIGS
- else:
- connection = get_connection(module)
- try:
- out = connection.get_config(flags=flags, format=format)
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
- cfg = to_text(out, errors="surrogate_then_replace").strip()
- _DEVICE_CONFIGS = cfg
- return cfg
-
-
-def run_commands(module, commands, check_rc=True):
- connection = get_connection(module)
- try:
- response = connection.run_commands(
- commands=commands, check_rc=check_rc
- )
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
- return response
-
-
-def load_config(module, commands, commit=False, comment=None):
- connection = get_connection(module)
-
- try:
- response = connection.edit_config(
- candidate=commands, commit=commit, comment=comment
- )
- except ConnectionError as exc:
- module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
-
- return response.get("diff")
diff -Nru ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/terminal/vyos.py ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/terminal/vyos.py
--- ansible-core-2.14.16/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/terminal/vyos.py 2024-04-22 20:07:35.000000000 +0200
+++ ansible-core-2.14.18/test/support/network-integration/collections/ansible_collections/vyos/vyos/plugins/terminal/vyos.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,53 +0,0 @@
-#
-# (c) 2016 Red Hat Inc.
-#
-# 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
-
-import os
-import re
-
-from ansible.plugins.terminal import TerminalBase
-from ansible.errors import AnsibleConnectionFailure
-
-
-class TerminalModule(TerminalBase):
-
- terminal_stdout_re = [
- re.compile(br"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
- re.compile(br"\@[\w\-\.]+:\S+?[>#\$] ?$"),
- ]
-
- terminal_stderr_re = [
- re.compile(br"\n\s*Invalid command:"),
- re.compile(br"\nCommit failed"),
- re.compile(br"\n\s+Set failed"),
- ]
-
- terminal_length = os.getenv("ANSIBLE_VYOS_TERMINAL_LENGTH", 10000)
-
- def on_open_shell(self):
- try:
- for cmd in (b"set terminal length 0", b"set terminal width 512"):
- self._exec_cli_command(cmd)
- self._exec_cli_command(
- b"set terminal length %d" % self.terminal_length
- )
- except AnsibleConnectionFailure:
- raise AnsibleConnectionFailure("unable to set terminal parameters")
Reply to: