Set HostVars._variable_manager's attrs (#65508)
When HostVars are part of the data that goes through (de)serialization when being passed from a worker process to the main process, its variable manager reference loses some of its attributes due to the implementation of __getstate__ and __setstate__ (perf utilization). Since HostVars already has those attributes, use __setstate__ to assign them. Fixes #65365
This commit is contained in:
parent
0c4f167b82
commit
ec371eb227
6 changed files with 29 additions and 1 deletions
2
changelogs/fragments/65365-fix-tb-printing-hostvars.yml
Normal file
2
changelogs/fragments/65365-fix-tb-printing-hostvars.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- Fix traceback when printing ``HostVars`` on native Jinja2 (https://github.com/ansible/ansible/issues/65365)
|
|
@ -49,7 +49,6 @@ class HostVars(Mapping):
|
||||||
''' A special view of vars_cache that adds values from the inventory when needed. '''
|
''' A special view of vars_cache that adds values from the inventory when needed. '''
|
||||||
|
|
||||||
def __init__(self, inventory, variable_manager, loader):
|
def __init__(self, inventory, variable_manager, loader):
|
||||||
self._lookup = dict()
|
|
||||||
self._inventory = inventory
|
self._inventory = inventory
|
||||||
self._loader = loader
|
self._loader = loader
|
||||||
self._variable_manager = variable_manager
|
self._variable_manager = variable_manager
|
||||||
|
@ -77,6 +76,19 @@ class HostVars(Mapping):
|
||||||
|
|
||||||
return self._variable_manager.get_vars(host=host, include_hostvars=False)
|
return self._variable_manager.get_vars(host=host, include_hostvars=False)
|
||||||
|
|
||||||
|
def __setstate__(self, state):
|
||||||
|
self.__dict__.update(state)
|
||||||
|
|
||||||
|
# Methods __getstate__ and __setstate__ of VariableManager do not
|
||||||
|
# preserve _loader and _hostvars attributes to improve pickle
|
||||||
|
# performance and memory utilization. Since HostVars holds values
|
||||||
|
# of those attributes already, assign them if needed.
|
||||||
|
if self._variable_manager._loader is None:
|
||||||
|
self._variable_manager._loader = self._loader
|
||||||
|
|
||||||
|
if self._variable_manager._hostvars is None:
|
||||||
|
self._variable_manager._hostvars = self
|
||||||
|
|
||||||
def __getitem__(self, host_name):
|
def __getitem__(self, host_name):
|
||||||
data = self.raw_get(host_name)
|
data = self.raw_get(host_name)
|
||||||
if isinstance(data, AnsibleUndefined):
|
if isinstance(data, AnsibleUndefined):
|
||||||
|
|
|
@ -133,6 +133,8 @@ class VariableManager:
|
||||||
self._inventory = data.get('inventory', None)
|
self._inventory = data.get('inventory', None)
|
||||||
self._options_vars = data.get('options_vars', dict())
|
self._options_vars = data.get('options_vars', dict())
|
||||||
self.safe_basedir = data.get('safe_basedir', False)
|
self.safe_basedir = data.get('safe_basedir', False)
|
||||||
|
self._loader = None
|
||||||
|
self._hostvars = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_vars(self):
|
def extra_vars(self):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
host1
|
|
@ -4,3 +4,4 @@ set -eux
|
||||||
|
|
||||||
ANSIBLE_JINJA2_NATIVE=1 ansible-playbook -i inventory.jinja2_native_types runtests.yml -v "$@"
|
ANSIBLE_JINJA2_NATIVE=1 ansible-playbook -i inventory.jinja2_native_types runtests.yml -v "$@"
|
||||||
ANSIBLE_JINJA2_NATIVE=1 ansible-playbook -i inventory.jinja2_native_types --vault-password-file test_vault_pass test_vault.yml -v "$@"
|
ANSIBLE_JINJA2_NATIVE=1 ansible-playbook -i inventory.jinja2_native_types --vault-password-file test_vault_pass test_vault.yml -v "$@"
|
||||||
|
ANSIBLE_JINJA2_NATIVE=1 ansible-playbook -i inventory.jinja2_native_types test_hostvars.yml -v "$@"
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
- hosts: host1
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- name: Print vars
|
||||||
|
debug:
|
||||||
|
var: vars
|
||||||
|
|
||||||
|
- name: Print hostvars
|
||||||
|
debug:
|
||||||
|
var: hostvars
|
Loading…
Reference in a new issue