cobbler.inventory: Allow collecting fully rendered facts (#9975)
Some checks are pending
EOL CI / EOL Sanity (Ⓐ2.15) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.15+py2.7) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.15+py3.10) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.15+py3.5) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/3/) (push) Waiting to run
nox / Run extra sanity tests (push) Waiting to run

Add facts_level option to cobbler inventory plugin, cleanpu

Initialize connection in parse()
Handle rendered system data in _get_systems() so it can be cached

Signed-off-by: Orion Poplawski <orion@nwra.com>
Co-authored-by: Tyler Phillippe <tylerphillippe@tutamail.com>
This commit is contained in:
Orion Poplawski 2025-04-26 04:34:11 -06:00 committed by GitHub
parent 373334d668
commit 7524e74bb7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 22 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- cobbler inventory plugin - add ``facts_level`` option to allow requesting fully rendered variables for Cobbler systems (https://github.com/ansible-collections/community.general/issues/9419, https://github.com/ansible-collections/community.general/pull/9975).

View file

@ -94,16 +94,24 @@ DOCUMENTATION = '''
description: Prefix to apply to cobbler groups.
default: cobbler_
want_facts:
description: Toggle, if V(true) the plugin will retrieve host facts from the server.
description: Toggle, if V(true) the plugin will retrieve all host facts from the server.
type: boolean
default: true
want_ip_addresses:
description:
- Toggle, if V(true) the plugin will add a C(cobbler_ipv4_addresses) and C(cobbleer_ipv6_addresses) dictionary to the defined O(group) mapping
- Toggle, if V(true) the plugin will add a C(cobbler_ipv4_addresses) and C(cobbler_ipv6_addresses) dictionary to the defined O(group) mapping
interface DNS names to IP addresses.
type: boolean
default: true
version_added: 7.1.0
facts_level:
description:
- "Set to V(normal) to gather only system-level variables."
- "Set to V(as_rendered) to gather all variables as rolled up by Cobbler."
type: string
choices: [ 'normal', 'as_rendered' ]
default: normal
version_added: 10.7.0
'''
EXAMPLES = '''
@ -142,7 +150,9 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
def __init__(self):
super(InventoryModule, self).__init__()
self.cache_key = None
self.connection = None
if not HAS_XMLRPC_CLIENT:
raise AnsibleError('Could not import xmlrpc client library')
def verify_file(self, path):
valid = False
@ -153,18 +163,6 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
self.display.vvv('Skipping due to inventory source not ending in "cobbler.yaml" nor "cobbler.yml"')
return valid
def _get_connection(self):
if not HAS_XMLRPC_CLIENT:
raise AnsibleError('Could not import xmlrpc client library')
if self.connection is None:
self.display.vvvv(f'Connecting to {self.cobbler_url}\n')
self.connection = xmlrpc_client.Server(self.cobbler_url, allow_none=True)
self.token = None
if self.get_option('user') is not None:
self.token = self.connection.login(text_type(self.get_option('user')), text_type(self.get_option('password')))
return self.connection
def _init_cache(self):
if self.cache_key not in self._cache:
self._cache[self.cache_key] = {}
@ -178,12 +176,11 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
def _get_profiles(self):
if not self.use_cache or 'profiles' not in self._cache.get(self.cache_key, {}):
c = self._get_connection()
try:
if self.token is not None:
data = c.get_profiles(self.token)
data = self.cobbler.get_profiles(self.token)
else:
data = c.get_profiles()
data = self.cobbler.get_profiles()
except (socket.gaierror, socket.error, xmlrpc_client.ProtocolError):
self._reload_cache()
else:
@ -194,12 +191,20 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
def _get_systems(self):
if not self.use_cache or 'systems' not in self._cache.get(self.cache_key, {}):
c = self._get_connection()
try:
if self.token is not None:
data = c.get_systems(self.token)
data = self.cobbler.get_systems(self.token)
else:
data = c.get_systems()
data = self.cobbler.get_systems()
# If more facts are requested, gather them all from Cobbler
if self.facts_level == "as_rendered":
for i, host in enumerate(data):
self.display.vvvv(f"Gathering all facts for {host['name']}\n")
if self.token is not None:
data[i] = self.cobbler.get_system_as_rendered(host['name'], self.token)
else:
data[i] = self.cobbler.get_system_as_rendered(host['name'])
except (socket.gaierror, socket.error, xmlrpc_client.ProtocolError):
self._reload_cache()
else:
@ -229,6 +234,12 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
# get connection host
self.cobbler_url = self.get_option('url')
self.display.vvvv(f'Connecting to {self.cobbler_url}\n')
self.cobbler = xmlrpc_client.Server(self.cobbler_url, allow_none=True)
self.token = None
if self.get_option('user') is not None:
self.token = self.cobbler.login(text_type(self.get_option('user')), text_type(self.get_option('password')))
self.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache')
@ -238,6 +249,7 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
self.include_profiles = self.get_option('include_profiles')
self.group_by = self.get_option('group_by')
self.inventory_hostname = self.get_option('inventory_hostname')
self.facts_level = self.get_option('facts_level')
for profile in self._get_profiles():
if profile['parent']:
@ -319,7 +331,7 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
# Add host to groups specified by group_by fields
for group_by in self.group_by:
if host[group_by] == '<<inherit>>':
if host[group_by] == '<<inherit>>' or host[group_by] == '':
groups = []
else:
groups = [host[group_by]] if isinstance(host[group_by], str) else host[group_by]