Skip to content

Commit

Permalink
Revive tests
Browse files Browse the repository at this point in the history
This PR gets the tests to pass with all the latest minor versions of all currently existing Python and Ansible versions.  It was not pleasant work. There have been a lot of Ansible versions and a lot of Python versions and a lot of changes to... just about everything involved here... since I last had the time to work on this!

By some miracle, the plugin itself has *NOT* needed *ANY* changes.  It still totally works.

* Add new Python and Ansible version combos to the generated tox.ini
* Restrict the Jinja2 version for some combos because it was [too broadly specified in the Ansible deps](ansible/ansible#77356)
* Remove the [deprecated](ansible/ansible#75828) `Templar.set_available_variables` method in a test util function (luckily there is another way to do this that works for all Ansible versions)
* Run each job in official python images: the [setup-python](https://github.com/actions/setup-python) action [no longer supports 2.7](actions/setup-python#672), and not all 3.x versions can be installed in the same Ubuntu runner anyway.
* Don't use [tox-gh-actions](https://pypi.org/project/tox-gh-actions/): the version that supports running in containers isn't compatible with all of the python versions that we need [issue](https://github.com/ymyzk/tox-gh-actions/pull/114/files)
* Restrict tox to a version that both supports Python 2.7 and supports filtering envs
* Explicitly call out `asdf` dependency for getting all tox combos to pass locally
* Add a link to [a proposed alternative way to do this](leapfrogonline#43) with pure Ansible to the Readme
  • Loading branch information
fajpunk committed Dec 18, 2023
1 parent b812d5b commit 1623e65
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 137 deletions.
67 changes: 48 additions & 19 deletions .github/workflows/ci.yaml
Expand Up @@ -12,35 +12,64 @@ on:

workflow_dispatch:


jobs:
test:
runs-on: ubuntu-latest
strategy:
max-parallel: 5
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9]

python-version:
- image: '2.7'
tox: py27
- image: '3.5'
tox: py35
- image: '3.6'
tox: py36
- image: '3.7'
tox: py37
- image: '3.8'
tox: py38
- image: '3.9'
tox: py39
- image: '3.10'
tox: py310
- image: '3.11'
tox: py311
- image: '3.12'
tox: py312
container:
image: python:${{ matrix.python-version.image }}
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
- name: Free disk space
# https://github.com/actions/virtual-environments/issues/709
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
echo "=========original CI disk space"
df -h
rm -rf "/usr/local/share/boost"
rm -rf "$AGENT_TOOLSDIRECTORY"
echo "=========after clean up, the left CI disk space"
df -h
- uses: actions/checkout@v4

- name: Test with tox
run: make ci-test
env:
# Can't include envs by regex, only exclude them :|
TOX_SKIP_ENV: '^(?!${{ matrix.python-version.tox }}-)'
run: |
set -x
pip install -U -r requirements.txt
python tests/bin/generate_tox_config.py
env | grep TOX
tox
lint:
runs-on: ubuntu-latest
container:
image: python:3.12
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- uses: actions/checkout@v4

- name: Lint
run: make lint
run: |
apt-get update && apt-get install make
make lint
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -96,3 +96,5 @@ ENV/

# Generated MANIFEST
MANIFEST

.idea
59 changes: 5 additions & 54 deletions .pylintrc
Expand Up @@ -10,61 +10,12 @@
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=
import-star-module-level,
old-octal-literal,
oct-method,
print-statement,
unpacking-in-except,
parameter-unpacking,
backtick,
old-raise-syntax,
old-ne-operator,
long-suffix,
dict-view-method,
dict-iter-method,
metaclass-assignment,
next-method-called,
raising-string,
indexing-exception,
raw_input-builtin,
long-builtin,
file-builtin,
execfile-builtin,
coerce-builtin,
cmp-builtin,
buffer-builtin,
basestring-builtin,
apply-builtin,
filter-builtin-not-iterating,
using-cmp-argument,
useless-suppression,
range-builtin-not-iterating,
suppressed-message,
no-absolute-import,
old-division,
cmp-method,
reload-builtin,
zip-builtin-not-iterating,
intern-builtin,
unichr-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
input-builtin,
round-builtin,
hex-method,
nonzero-method,
map-builtin-not-iterating,
too-few-public-methods,
similarities,
missing-docstring,
consider-using-f-string,
redundant-u-string-prefix,
consider-using-f-string
missing-function-docstring,
missing-class-docstring,
missing-module-docstring,
R0801, # similar lines in two files

[REPORTS]

Expand Down
6 changes: 0 additions & 6 deletions .python-version

This file was deleted.

1 change: 1 addition & 0 deletions .tool-versions
@@ -0,0 +1 @@
python 3.12.1 3.6.12 3.5.10 3.7.9 3.8.6 3.9.0 3.10.13 3.11.7 2.7.18
7 changes: 0 additions & 7 deletions Makefile
Expand Up @@ -23,13 +23,6 @@ lint: dev-deps generate-tox-config
test-all: dev-deps generate-tox-config
$(TOX) --parallel auto

# No venv needed in CI; let the GH Actions tox plugin handle the Python
# versions
ci-test:
pip install -U -r requirements.txt
python tests/bin/generate_tox_config.py
tox

clean:
rm -rf venv .tox .hypothesis dist tox.ini

Expand Down
61 changes: 37 additions & 24 deletions README.md
Expand Up @@ -3,6 +3,16 @@
![CI](https://github.com/leapfrogonline/ansible-merge-vars/workflows/ci/badge.svg?branch=master)
[![PyPI](https://img.shields.io/pypi/v/ansible_merge_vars.svg)](https://pypi.org/project/ansible_merge_vars/)

## You probably don't need this!
As of [March 2023](https://github.com/ansible-collections/community.general/commit/f52dd194f917fa3162b158b762808aff886c27f1), the [merge_variables lookup](https://docs.ansible.com/ansible/latest/collections/community/general/merge_variables_lookup.html) is in the [Community.General collection](https://docs.ansible.com/ansible/latest/collections/community/general/index.html)
The differences between that and this plugin are:
* This plugin has an option to dedup lists when creating the merged var. You can [unique filter](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unique_filter.html) with the new lookup for that.
* This plugin has the option to non-recursively merge dicts. You probably always want to recursively merge them, which the new look up does.

The only reason you probably want to use this plugin instead of the lookup is if you are stuck using an older version of Ansible or can't otherwise use the built-in lookup.
That said...

## Overview
An Ansible plugin to merge all variables in context with a certain suffix (lists
or dicts only) and create a new variable that contains the result of this merge.
This is an Ansible action plugin, which is basically an Ansible module that runs
Expand All @@ -27,9 +37,12 @@ newer versions of Python. The following combinations are tested:
| Python | Ansible |
|---------------|---------|
| 2.7 | >= 2.1 |
| >= 3.5, < 3.8 | >= 2.5 |
| >= 3.7, < 3.8 | >= 2.5 |
| >= 3.8 | >= 2.8 |

Above Ansible 2.8, _at least_ all of the combinations in the [Ansible Core Support Matrix](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix)
are tested. Some other combinations are tested too (even if the Ansible maintainers [may get salty about it](https://github.com/ansible/ansible/issues/81946))

## Installation

1. Pick a name that you want to use to call this plugin in Ansible playbooks.
Expand Down Expand Up @@ -216,7 +229,7 @@ merged_ports:
A note about `dedup`:
* It has no effect when the merged vars are dictionaries.

### Recursive merging ###
### Recursive merging

When dealing with complex data structures, you may want to do a deep (recursive) merge.

Expand Down Expand Up @@ -272,7 +285,7 @@ When merging dictionaries and the same key exists in both, the recursive merge c
* if the entry value is a dict, it merges the values (recursively) as dicts (merge_dict)
* any other values: just replace (use last)

### Module options ###
### Module options

| parameter | required | default | choices | comments |
| --------- | -------- | ------- | ------- | -------- |
Expand Down Expand Up @@ -309,7 +322,7 @@ PLAY RECAP *********************************************************************
localhost : ok=6 changed=0 unreachable=0 failed=0
```

## Example Playbooks
## Example playbooks

There are some example playbooks in the `examples` directory that show how the
various features work in the context of an actual Ansible playbook. These
Expand All @@ -323,9 +336,9 @@ Please note that this project is released with a [Contributor Code of Conduct](C

There is only one prerequisite to working on this project locally:

1. You have the Python versions in the [.python-version](.python-version)
1. You have the Python versions in the [.tool-versions](.tool-versions)
installed and on your path (probably with
[pyenv](https://github.com/pyenv/pyenv)
[asdf](https://asdf-vm.com/)

A development workflow may look like this:

Expand All @@ -347,24 +360,24 @@ A development workflow may look like this:
available and tell tox to only run the tests for one combination:

```
$ venv/bin/tox -l
py27-ansible-2.1
py27-ansible-2.2
py27-ansible-2.3
py27-ansible-2.4
py27-ansible-2.5
py27-ansible-2.6
...
py35-ansible-2.5
py35-ansible-2.6
py36-ansible-2.7
py36-ansible-2.8
...
$ venv/bin/tox -e py36-ansible-2.5
...
```
$ venv/bin/tox -l
py27-ansible-2.1
py27-ansible-2.2
py27-ansible-2.3
py27-ansible-2.4
py27-ansible-2.5
py27-ansible-2.6
...
py37-ansible-2.5
py37-ansible-2.6
py38-ansible-2.7
py38-ansible-2.8
...
...
$ venv/bin/tox -e py36-ansible-2.5
```

If you have any ideas about things to add or improve, or find any bugs to fix, we're all ears! Just a few guidelines:

Expand Down
6 changes: 5 additions & 1 deletion requirements.txt
@@ -1,6 +1,10 @@
# Explicitly not pinnning most versions here to get valid versions for different python versions
pip
setuptools
wheel
twine
tox

# TOX_SKIP_ENV broke with an earlier version of 4, but we can't use the latest 4 with 2.7 :|
# https://github.com/tox-dev/tox/issues/2698
tox<4
requests
62 changes: 51 additions & 11 deletions tests/bin/generate_tox_config.py
Expand Up @@ -22,16 +22,28 @@
TOX_INI = os.path.join(ROOT_DIR, 'tox.ini')


def filter_releases(releases, min_release):
def filter_releases(releases, min_release, max_release=None):
"""
min_release inclusive, max_release exclusive
"""
finished = [release for release in releases
if not re.search(r'[a-zA-z]', release)]
minor = list(set(
[re.match(r'^(\d+\.\d+)', release).groups()[0] for release in finished]
))
relevant = [
release for release in minor
if LooseVersion(release) >= LooseVersion(min_release)
]

relevant = minor
if min_release:
relevant = [
release for release in relevant
if LooseVersion(release) >= LooseVersion(min_release)
]

if max_release:
relevant = [
release for release in relevant
if LooseVersion(release) < LooseVersion(max_release)
]
return sorted(relevant, key=LooseVersion)


Expand All @@ -43,24 +55,52 @@ def tox_dep_specs(releases):
return '\n'.join(spec_strings)


def jinja_dep_specs(releases):
spec_strings = [
' ansible-{release}: jinja2<3.1'.format(release=release)
for release in releases
]
return '\n'.join(spec_strings)


def main():
# Get available releases
response = requests.get('https://pypi.python.org/pypi/ansible/json').json()
releases = response['releases'].keys()

py2_releases = filter_releases(releases, '2.1')
py3_releases = filter_releases(releases, '2.5')
py38_releases = filter_releases(releases, '2.8')
all_releases = filter_releases(releases, min_release='2.1')
py27_releases = filter_releases(releases, min_release='2.1', max_release='5.0')
py35_releases = filter_releases(releases, min_release='2.5', max_release='5.0')
py36_releases = filter_releases(releases, min_release='2.5', max_release='5.0')
py37_releases = filter_releases(releases, min_release='2.5', max_release='5.0')
py38_releases = filter_releases(releases, min_release='2.8', max_release='7.0')
py39_releases = filter_releases(releases, min_release='2.8', max_release='9.0')
py310_releases = filter_releases(releases, min_release='2.8')
py311_releases = filter_releases(releases, min_release='2.8')

# https://github.com/ansible/ansible/issues/81946
py312_releases = filter_releases(releases, min_release='6.0')

# Some old releases didn't constrain Jinja properly and a newer version breaks some filters
# https://github.com/ansible/ansible/issues/77356
old_jinja_releases = filter_releases(releases, min_release=None, max_release='2.10')

print('Reading template {}'.format(TOX_TMPL))
with open(TOX_TMPL, 'r') as f:
tmpl = Template(f.read())

generated = tmpl.substitute(
py2_releases=','.join(py2_releases),
py3_releases=','.join(py3_releases),
py27_releases=','.join(py27_releases),
py35_releases=','.join(py35_releases),
py36_releases=','.join(py36_releases),
py37_releases=','.join(py37_releases),
py38_releases=','.join(py38_releases),
ansible_dep_specs=tox_dep_specs(py2_releases)
py39_releases=','.join(py39_releases),
py310_releases=','.join(py310_releases),
py311_releases=','.join(py311_releases),
py312_releases=','.join(py312_releases),
ansible_dep_specs=tox_dep_specs(all_releases),
jinja_dep_specs=jinja_dep_specs(old_jinja_releases)
)
print('\nWriting {TOX_INI}:\n{generated}'.format(TOX_INI=TOX_INI, generated=generated))

Expand Down

0 comments on commit 1623e65

Please sign in to comment.