Merge "Bump up Ansible supported versions to 11.x/12.x"

This commit is contained in:
Zuul
2025-11-13 14:53:20 +00:00
committed by Gerrit Code Review
20 changed files with 219 additions and 56 deletions

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2025 StackHPC Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
__metaclass__ = type
import kayobe.plugins.action.template_content
ActionModule = kayobe.plugins.action.template_content.ActionModule

View File

@@ -93,7 +93,7 @@
kolla_ansible_passwords_path: "{{ kayobe_env_config_path }}/kolla/passwords.yml"
kolla_overcloud_inventory_search_paths_static:
- "{{ kayobe_config_path }}"
kolla_overcloud_inventory_search_paths: "{{ kolla_overcloud_inventory_search_paths_static + kayobe_env_search_paths }}"
kolla_overcloud_inventory_search_paths: "{{ kolla_overcloud_inventory_search_paths_static + kayobe_env_search_paths | default([]) }}"
kolla_ansible_certificates_path: "{{ kayobe_env_config_path }}/kolla/certificates"
kolla_inspector_dhcp_pool_start: "{{ inspection_net_name | net_inspection_allocation_pool_start }}"
kolla_inspector_dhcp_pool_end: "{{ inspection_net_name | net_inspection_allocation_pool_end }}"
@@ -103,7 +103,7 @@
kolla_libvirt_tls: "{{ compute_libvirt_enable_tls | bool }}"
kolla_globals_paths_static:
- "{{ kayobe_config_path }}"
kolla_globals_paths_extra: "{{ kolla_globals_paths_static + kayobe_env_search_paths }}"
kolla_globals_paths_extra: "{{ kolla_globals_paths_static + kayobe_env_search_paths | default([]) }}"
kolla_ironic_inspector_host: "{{ groups[controller_ironic_inspector_group][0] if groups[controller_ironic_inspector_group] | length > 0 else '' }}"
- name: Generate Kolla Ansible host vars for the seed host

View File

@@ -26,7 +26,7 @@ kolla_ansible_venv_extra_requirements: []
# tested code. Changes to this limit should be tested. It is possible to only
# install ansible-core by setting kolla_ansible_venv_ansible to None.
kolla_ansible_venv_ansible:
kolla_ansible_venv_ansible_core: 'ansible-core>=2.17,<2.19'
kolla_ansible_venv_ansible_core: 'ansible-core>=2.18,<2.20'
# Path to a requirements.yml file for Ansible collections.
kolla_ansible_requirements_yml: "{{ kolla_ansible_venv }}/share/kolla-ansible/requirements.yml"

View File

@@ -141,7 +141,7 @@
- "{{ kolla_ansible_venv_ansible_core }}"
- "{{ kolla_ansible_venv_ansible }}"
pip:
name: "{{ (kolla_ansible_packages + kolla_ansible_venv_extra_requirements) | select | list }}"
name: "{{ (kolla_ansible_packages | default([]) + kolla_ansible_venv_extra_requirements | default([])) | select | list }}"
state: latest
extra_args: "{% if kolla_upper_constraints_file %}-c {{ kolla_upper_constraints_file }}{% endif %}"
virtualenv: "{{ kolla_ansible_venv }}"

View File

@@ -11,7 +11,7 @@
- block:
- name: Test the kolla-ansible role with default values
include_role:
name: ../../kolla-ansible
name: "{{ playbook_dir }}/.."
vars:
kolla_ansible_source_path: "{{ temp_path }}/src"
kolla_ansible_ctl_install_type: "source"

View File

@@ -119,11 +119,11 @@
params:
content: |
{%- for path in item.sources -%}
{{ lookup('template', path) }}
{{ lookup('file', path) }}
{%- endfor -%}
dest: "{{ item.dest }}"
mode: 0640
copy: "{{ params | combine(item.params) }}"
template_content: "{{ params | combine(item.params) }}"
with_items: "{{ kolla_custom_config_info.concat }}"
- name: Ensure unnecessary extra configuration files are absent

View File

@@ -21,7 +21,14 @@ import subprocess
import sys
import tempfile
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
# TODO(dougszu): Backwards compatibility for Ansible 11. This exception
# handler can be removed in the G cycle.
try:
from ansible.parsing.vault import EncryptedString
except ImportError:
# Ansible 11
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
EncryptedString = AnsibleVaultEncryptedUnicode
from kayobe import exception
from kayobe import utils
@@ -222,6 +229,9 @@ def _get_environment(parsed_args, external_playbook=False):
"""Return an environment dict for executing an Ansible playbook."""
env = os.environ.copy()
vault.update_environment(parsed_args, env)
# TODO(wszusmki): Kayobe still uses broken conditions. Work on fixing these
# and remove when that work is complete.
env.setdefault("ANSIBLE_ALLOW_BROKEN_CONDITIONALS", "true")
# If the configuration path has been specified via --config-path, ensure
# the environment variable is set, so that it can be referenced by
# playbooks.
@@ -340,7 +350,7 @@ def run_playbook(parsed_args, playbook, *args, **kwargs):
def _sanitise_hostvar(var):
"""Sanitise a host variable."""
if isinstance(var, AnsibleVaultEncryptedUnicode):
if isinstance(var, EncryptedString):
return "******"
# Recursively sanitise dicts and lists.
if isinstance(var, dict):

View File

@@ -14,6 +14,16 @@
from ansible.plugins.action import ActionBase
# TODO(dougszu): From Ansible 12 onwards we must explicitly trust templates.
# Since this feature is not supported in previous releases, we define a
# noop method here for backwards compatibility. This can be removed in the
# G cycle.
try:
from ansible.template import trust_as_template
except ImportError:
def trust_as_template(template):
return template
class ConfigError(Exception):
pass
@@ -28,6 +38,11 @@ class ActionModule(ActionBase):
TRANSFERS_FILES = False
def trusted_template(self, input):
# Mark all input as trusted.
trusted_input = trust_as_template(input)
return self._templar.template(trusted_input)
def run(self, tmp=None, task_vars=None):
if task_vars is None:
task_vars = dict()
@@ -97,11 +112,11 @@ class ActionModule(ActionBase):
def _get_interface_fact(self, net_name, required, description):
# Check whether the network is mapped to this host.
condition = "{{ '%s' in network_interfaces }}" % net_name
condition = self._templar.template(condition)
condition = self.trusted_template(condition)
if condition:
# Get the network interface for this network.
iface = ("{{ '%s' | net_interface }}" % net_name)
iface = self._templar.template(iface)
iface = self.trusted_template(iface)
if required and not iface:
msg = ("Required network '%s' (%s) does not have an interface "
"configured for this host" % (net_name, description))
@@ -114,20 +129,20 @@ class ActionModule(ActionBase):
def _get_external_interface(self, net_name, required):
condition = "{{ '%s' in network_interfaces }}" % net_name
condition = self._templar.template(condition)
condition = self.trusted_template(condition)
if condition:
iface = self._templar.template("{{ '%s' | net_interface }}" %
net_name)
iface = self.trusted_template("{{ '%s' | net_interface }}" %
net_name)
if iface:
# When these networks are VLANs, we need to use the
# underlying tagged bridge interface rather than the
# untagged interface. We therefore strip the .<vlan> suffix
# of the interface name. We use a union here as a single
# tagged interface may be shared between these networks.
vlan = self._templar.template("{{ '%s' | net_vlan }}" %
net_name)
parent = self._templar.template("{{ '%s' | net_parent }}" %
net_name)
vlan = self.trusted_template("{{ '%s' | net_vlan }}" %
net_name)
parent = self.trusted_template("{{ '%s' | net_parent }}" %
net_name)
if vlan and parent:
iface = parent
elif vlan and iface.endswith(".%s" % vlan):
@@ -146,15 +161,15 @@ class ActionModule(ActionBase):
neutron_external_interfaces = []
neutron_physical_networks = []
missing_physical_networks = []
bridge_suffix = self._templar.template(
bridge_suffix = self.trusted_template(
"{{ network_bridge_suffix_ovs }}")
patch_prefix = self._templar.template("{{ network_patch_prefix }}")
patch_suffix = self._templar.template("{{ network_patch_suffix_ovs }}")
patch_prefix = self.trusted_template("{{ network_patch_prefix }}")
patch_suffix = self.trusted_template("{{ network_patch_suffix_ovs }}")
for interface, iface_networks in external_interfaces.items():
is_bridge = ("{{ '%s' in (network_interfaces |"
"net_select_bridges |"
"map('net_interface')) }}" % interface)
is_bridge = self._templar.template(is_bridge)
is_bridge = self.trusted_template(is_bridge)
neutron_bridge_names.append(interface + bridge_suffix)
# For a bridge, use a veth pair connected to the bridge. Otherwise
# use the interface directly.
@@ -171,7 +186,7 @@ class ActionModule(ActionBase):
# attribute set, and if so, whether they are consistent.
iface_physical_networks = []
for iface_network in iface_networks:
physical_network = self._templar.template(
physical_network = self.trusted_template(
"{{ '%s' | net_physical_network }}" % iface_network)
if (physical_network and
physical_network not in iface_physical_networks):

View File

@@ -24,10 +24,21 @@ import tempfile
from ansible import constants
from ansible.plugins import action
# TODO(dougszu): From Ansible 12 onwards we must explicitly trust templates.
# Since this feature is not supported in previous releases, we define a
# noop method here for backwards compatibility. This can be removed in the
# G cycle.
try:
from ansible.template import trust_as_template
except ImportError:
def trust_as_template(template):
return template
from io import StringIO
from oslo_config import iniparser
_ORPHAN_SECTION = 'TEMPORARY_ORPHAN_VARIABLE_SECTION'
DOCUMENTATION = '''
@@ -154,7 +165,7 @@ class ActionModule(action.ActionBase):
# Only use config if present
if os.access(source, os.R_OK):
with open(source, 'r') as f:
template_data = f.read()
template_data = trust_as_template(f.read())
# set search path to mimic 'template' module behavior
searchpath = [

View File

@@ -27,6 +27,16 @@ from ansible import constants
from ansible import errors as ansible_errors
from ansible.plugins import action
# TODO(dougszu): From Ansible 12 onwards we must explicitly trust templates.
# Since this feature is not supported in previous releases, we define a
# noop method here for backwards compatibility. This can be removed in the
# G cycle.
try:
from ansible.template import trust_as_template
except ImportError:
def trust_as_template(template):
return template
DOCUMENTATION = '''
---
module: merge_yaml
@@ -95,7 +105,7 @@ class ActionModule(action.ActionBase):
# Only use config if present
if source and os.access(source, os.R_OK):
with open(source, 'r') as f:
template_data = f.read()
template_data = trust_as_template(f.read())
# set search path to mimic 'template' module behavior
searchpath = [

View File

@@ -0,0 +1,47 @@
# Copyright (c) 2025 StackHPC Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import tempfile
from ansible.module_utils.common.text.converters import to_bytes
from ansible.plugins.action.template import ActionModule as TemplateBase
from ansible import errors as ansible_errors
class ActionModule(TemplateBase):
"""Decorates template action to support using content parameter"""
def run(self, *args, **kwargs):
module_args = self._task.args
if "src" in module_args and "content" in module_args:
raise ansible_errors.AnsibleActionFail(
"Invalid argument: content and src are mutually exclusive."
)
if "content" not in module_args and "src" not in module_args:
raise ansible_errors.AnsibleActionFail(
"Invalid argument: You must speicfy either content or src"
)
if "src" in module_args:
return super().run(*args, **kwargs)
with tempfile.NamedTemporaryFile() as fp:
content = module_args.pop("content", "")
fp.write(to_bytes(content))
fp.flush()
tempfile_path = os.path.join(tempfile.gettempdir(), str(fp.name))
module_args["src"] = tempfile_path
return super().run(*args, **kwargs)

View File

@@ -28,6 +28,9 @@ from kayobe import exception
from kayobe import utils
from kayobe import vault
from ansible.parsing.vault import VaultSecret
from ansible.parsing.vault import VaultSecretsContext
@mock.patch.dict(os.environ, clear=True)
class TestCase(unittest.TestCase):
@@ -56,6 +59,7 @@ class TestCase(unittest.TestCase):
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": ":".join([
"/etc/kayobe/ansible/roles",
@@ -106,6 +110,7 @@ class TestCase(unittest.TestCase):
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": ":".join([
utils.get_data_files_path("ansible", "roles"),
@@ -223,6 +228,7 @@ class TestCase(unittest.TestCase):
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/path/to/config",
"KAYOBE_ENVIRONMENT": "test-env",
"ANSIBLE_ROLES_PATH": ":".join([
@@ -299,6 +305,7 @@ class TestCase(unittest.TestCase):
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/path/to/config",
"KAYOBE_ENVIRONMENT": "test-env",
"KAYOBE_VAULT_PASSWORD": "test-pass",
@@ -342,6 +349,7 @@ class TestCase(unittest.TestCase):
"playbook1.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": mock.ANY,
"ANSIBLE_COLLECTIONS_PATH": mock.ANY,
@@ -379,6 +387,7 @@ class TestCase(unittest.TestCase):
"playbook1.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"KAYOBE_VAULT_PASSWORD": "test-pass",
"ANSIBLE_ROLES_PATH": mock.ANY,
@@ -446,6 +455,7 @@ class TestCase(unittest.TestCase):
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": mock.ANY,
"ANSIBLE_COLLECTIONS_PATH": mock.ANY,
@@ -483,6 +493,7 @@ class TestCase(unittest.TestCase):
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": mock.ANY,
"ANSIBLE_COLLECTIONS_PATH": mock.ANY,
@@ -520,6 +531,7 @@ class TestCase(unittest.TestCase):
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": mock.ANY,
"ANSIBLE_COLLECTIONS_PATH": mock.ANY,
@@ -553,6 +565,7 @@ class TestCase(unittest.TestCase):
expected_env = {
"ANSIBLE_CONFIG": "/etc/kayobe/ansible.cfg",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"ANSIBLE_ROLES_PATH": mock.ANY,
"ANSIBLE_COLLECTIONS_PATH": mock.ANY,
"ANSIBLE_ACTION_PLUGINS": mock.ANY,
@@ -585,6 +598,7 @@ class TestCase(unittest.TestCase):
"playbook1.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"ANSIBLE_CONFIG": "/path/to/ansible.cfg",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": mock.ANY,
@@ -656,6 +670,10 @@ class TestCase(unittest.TestCase):
@mock.patch.object(tempfile, 'mkdtemp')
def test_config_dump_vaulted(self, mock_mkdtemp, mock_run, mock_listdir,
mock_read, mock_rmtree):
secret = VaultSecret(b'test-pass')
VaultSecretsContext.initialize(
VaultSecretsContext(secrets=[('default', secret)]))
parser = argparse.ArgumentParser()
parsed_args = parser.parse_args([])
dump_dir = "/path/to/dump"
@@ -663,31 +681,31 @@ class TestCase(unittest.TestCase):
mock_listdir.return_value = ["host1.yml", "host2.yml"]
config = """---
key1: !vault |
$ANSIBLE_VAULT;1.1;AES256
633230623736383232323862393364323037343430393530316636363961626361393133646437
643438663261356433656365646138666133383032376532310a63323432306431303437623637
346236316161343635636230613838316566383933313338636237616338326439616536316639
6334343462333062363334300a3930313762313463613537626531313230303731343365643766
666436333037
$ANSIBLE_VAULT;1.1;AES256
65393836643335346138373665636564643436353231623838636261373565633731303835653139
6335343464383063373734636161323236636431316532650a333366333366396262353635313531
64666236636262326662323931313065376533333961356239363637333363623464666636616233
6130373664393533350a663266613165646565346433313536313461653236303563643262323936
6262
key2: value2
key3:
- !vault |
$ANSIBLE_VAULT;1.1;AES256
633230623736383232323862393364323037343430393530316636363961626361393133646437
643438663261356433656365646138666133383032376532310a63323432306431303437623637
346236316161343635636230613838316566383933313338636237616338326439616536316639
6334343462333062363334300a3930313762313463613537626531313230303731343365643766
666436333037
65393836643335346138373665636564643436353231623838636261373565633731303835653139
6335343464383063373734636161323236636431316532650a333366333366396262353635313531
64666236636262326662323931313065376533333961356239363637333363623464666636616233
6130373664393533350a663266613165646565346433313536313461653236303563643262323936
6262
"""
config_nested = """---
key1:
key2: !vault |
$ANSIBLE_VAULT;1.1;AES256
633230623736383232323862393364323037343430393530316636363961626361393133646437
643438663261356433656365646138666133383032376532310a63323432306431303437623637
346236316161343635636230613838316566383933313338636237616338326439616536316639
6334343462333062363334300a3930313762313463613537626531313230303731343365643766
666436333037
65393836643335346138373665636564643436353231623838636261373565633731303835653139
6335343464383063373734636161323236636431316532650a333366333366396262353635313531
64666236636262326662323931313065376533333961356239363637333363623464666636616233
6130373664393533350a663266613165646565346433313536313461653236303563643262323936
6262
"""
mock_read.side_effect = [config, config_nested]
result = ansible.config_dump(parsed_args)
@@ -951,6 +969,7 @@ key1:
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"ANSIBLE_ROLES_PATH": mock.ANY,
"ANSIBLE_COLLECTIONS_PATH": mock.ANY,
@@ -994,6 +1013,7 @@ key1:
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"KAYOBE_ENVIRONMENT": "test-env",
"ANSIBLE_ROLES_PATH": mock.ANY,
@@ -1036,6 +1056,7 @@ key1:
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"KAYOBE_ENVIRONMENT": "test-env",
"ANSIBLE_ROLES_PATH": mock.ANY,
@@ -1079,6 +1100,7 @@ key1:
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"KAYOBE_ENVIRONMENT": "test-env",
"ANSIBLE_ROLES_PATH": mock.ANY,
@@ -1127,6 +1149,7 @@ key1:
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"KAYOBE_ENVIRONMENT": "test-env",
"ANSIBLE_ROLES_PATH": mock.ANY,
@@ -1207,6 +1230,7 @@ key1:
"playbook2.yml",
]
expected_env = {
"ANSIBLE_ALLOW_BROKEN_CONDITIONALS": "true",
"KAYOBE_CONFIG_PATH": "/etc/kayobe",
"KAYOBE_ENVIRONMENT": "test-env",
"ANSIBLE_ROLES_PATH": mock.ANY,

View File

@@ -18,7 +18,15 @@ import subprocess
import unittest
from unittest import mock
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
# TODO(dougszu): Backwards compatibility for Ansible 11. This exception
# handler can be removed in the G cycle.
try:
from ansible.parsing.vault import EncryptedString
except ImportError:
# Ansible 11
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
EncryptedString = AnsibleVaultEncryptedUnicode
import yaml
from kayobe import exception
@@ -167,9 +175,9 @@ key3:
mock_read.return_value = config
result = utils.read_config_dump_yaml_file("/path/to/file")
# Can't read the value without an encryption key, so just check type.
self.assertIsInstance(result["key1"], AnsibleVaultEncryptedUnicode)
self.assertIsInstance(result["key1"], EncryptedString)
self.assertEqual(result["key2"], "value2")
self.assertIsInstance(result["key3"][0], AnsibleVaultEncryptedUnicode)
self.assertIsInstance(result["key3"][0], EncryptedString)
mock_read.assert_called_once_with("/path/to/file")
@mock.patch.object(utils, "read_file")

View File

@@ -189,7 +189,8 @@ def read_config_dump_yaml_file(path):
sys.exit(1)
try:
# AnsibleLoader supports loading vault encrypted variables.
return AnsibleLoader(content).get_single_data()
data = AnsibleLoader(content).get_single_data()
return data
except yaml.YAMLError as e:
print("Failed to decode config dump YAML file %s: %s" %
(path, repr(e)))

View File

@@ -11,11 +11,15 @@
---
- hosts: localhost
tasks:
- name: Testing become fails
command: "true"
become: true
register: result
failed_when: '"CONTROL_HOST_BECOME_VIOLATION" not in result.module_stderr'
- block:
- name: Testing become fails
command: "true"
become: true
register: result
rescue:
- name: Check for become failure
fail:
when: '"CONTROL_HOST_BECOME_VIOLATION" not in result.msg'
dest: /tmp/test-control-host-become.yml
- name: Check that that kayobe become validator was correctly configured

View File

@@ -0,0 +1,6 @@
---
upgrade:
- |
Updates the maximum supported version of Ansible from 12 (ansible-core
2.18) to 13 (ansible-core 2.19). The minimum supported version is updated
from 10.x to 11.x. This is true for both Kayobe and Kolla Ansible.

View File

@@ -1,6 +1,6 @@
pbr>=2.0 # Apache-2.0
Jinja2>3 # BSD
ansible>=10,<12 # GPLv3
ansible>=11,<13 # GPLv3
cliff>=3.1.0 # Apache
netaddr!=0.7.16,>=0.7.13 # BSD
PyYAML>=3.10.0 # MIT

View File

@@ -29,9 +29,9 @@ roles:
version: 1.3.1
- src: giovtorres.tuned
version: 1.2.0
- src: jriguera.configdrive
# There are no versioned releases of this role.
version: 71ddface5540ee0ff9e35bcc4334c766ed5d5d3f
- src: git+https://github.com/stackhpc/ansible-role-configdrive.git
name: jriguera.configdrive
version: fb199247333e72e38a9d414cf7b6144daa645477
- src: MichaelRigart.interfaces
version: v1.15.6
- src: mrlesmithjr.chrony
@@ -46,8 +46,9 @@ roles:
version: 1.1.6
- src: stackhpc.drac-facts
version: 1.0.0
- src: stackhpc.libvirt-host
version: v1.14.0
- src: git+https://github.com/stackhpc/ansible-role-libvirt-host.git
name: stackhpc.libvirt-host
version: 9a947f74abdcd2e0d4e3371162f8299aef259271
- src: stackhpc.libvirt-vm
version: v1.16.3
- src: stackhpc.luks

View File

@@ -17,6 +17,7 @@ setenv =
OS_STDOUT_CAPTURE=1
OS_STDERR_CAPTURE=1
OS_TEST_TIMEOUT=60
ANSIBLE_VERBOSITY=3
deps =
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt

View File

@@ -9,6 +9,9 @@
- release-notes-jobs-python3
check:
jobs:
- openstack-tox-py310:
#NOTE(wszumski): We have dropped python3.10 support, so disable this job.
files: THIS-JOB-IS-DISABLED
- kayobe-tox-ansible-syntax
- kayobe-tox-ansible
- kayobe-tox-molecule
@@ -31,6 +34,9 @@
- kayobe-seed-vm-ubuntu-noble
gate:
jobs:
- openstack-tox-py310:
#NOTE(wszumski): We have dropped python3.10 support, so disable this job.
files: THIS-JOB-IS-DISABLED
- kayobe-tox-ansible-syntax
- kayobe-tox-ansible
- kayobe-tox-molecule