Skip to content

Commit

Permalink
Add option to proxmox dynamic inventory to exclude nodes (#7461)
Browse files Browse the repository at this point in the history
* Create option to exclude proxmox nodes

* improve node exclusion by only remove the top level group

* add fragment

* Update changelogs/fragments/7437-proxmox-inventory-add-exclude-nodes.yaml

Co-authored-by: Felix Fontein <[email protected]>

* Update plugins/inventory/proxmox.py

Co-authored-by: Felix Fontein <[email protected]>

* Rework node exclusion

* Update fragement PR number

* include release version in option

Co-authored-by: Felix Fontein <[email protected]>

* Clarify description

* Update unit test

* Fix typos in unit test

* Fix additonal typos in test

* Fix CI

* Fixing yet another whitespace pep error

---------

Co-authored-by: Felix Fontein <[email protected]>
  • Loading branch information
IamLunchbox and felixfontein authored Nov 26, 2023
1 parent 938aec4 commit d05932f
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- proxmox inventory plugin - adds an option to exclude nodes from the dynamic inventory generation. The new setting is optional, not using this option will behave as usual (https://github.com/ansible-collections/community.general/issues/6714, https://github.com/ansible-collections/community.general/pull/7461).
24 changes: 15 additions & 9 deletions plugins/inventory/proxmox.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@
- The default of this option changed from V(true) to V(false) in community.general 6.0.0.
type: bool
default: false
exclude_nodes:
description: Exclude proxmox nodes and the nodes-group from the inventory output.
type: bool
default: false
version_added: 8.1.0
filters:
version_added: 4.6.0
description: A list of Jinja templates that allow filtering hosts.
Expand Down Expand Up @@ -565,9 +570,9 @@ def _populate(self):

for group in default_groups:
self.inventory.add_group(self._group('all_%s' % (group)))

nodes_group = self._group('nodes')
self.inventory.add_group(nodes_group)
if not self.exclude_nodes:
self.inventory.add_group(nodes_group)

want_proxmox_nodes_ansible_host = self.get_option("want_proxmox_nodes_ansible_host")

Expand All @@ -577,22 +582,23 @@ def _populate(self):
for node in self._get_nodes():
if not node.get('node'):
continue

self.inventory.add_host(node['node'])
if node['type'] == 'node':
if not self.exclude_nodes:
self.inventory.add_host(node['node'])
if node['type'] == 'node' and not self.exclude_nodes:
self.inventory.add_child(nodes_group, node['node'])

if node['status'] == 'offline':
continue

# get node IP address
if want_proxmox_nodes_ansible_host:
if want_proxmox_nodes_ansible_host and not self.exclude_nodes:
ip = self._get_node_ip(node['node'])
self.inventory.set_variable(node['node'], 'ansible_host', ip)

# Setting composite variables
variables = self.inventory.get_host(node['node']).get_vars()
self._set_composite_vars(self.get_option('compose'), variables, node['node'], strict=self.strict)
if not self.exclude_nodes:
variables = self.inventory.get_host(node['node']).get_vars()
self._set_composite_vars(self.get_option('compose'), variables, node['node'], strict=self.strict)

# add LXC/Qemu groups for the node
for ittype in ('lxc', 'qemu'):
Expand Down Expand Up @@ -635,8 +641,8 @@ def parse(self, inventory, loader, path, cache=True):

if self.get_option('qemu_extended_statuses') and not self.get_option('want_facts'):
raise AnsibleError('You must set want_facts to True if you want to use qemu_extended_statuses.')

# read rest of options
self.exclude_nodes = self.get_option('exclude_nodes')
self.cache_key = self.get_cache_key(path)
self.use_cache = cache and self.get_option('cache')
self.host_filters = self.get_option('filters')
Expand Down
45 changes: 43 additions & 2 deletions tests/unit/plugins/inventory/test_proxmox.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,13 +646,15 @@ def test_populate(inventory, mocker):
inventory.group_prefix = 'proxmox_'
inventory.facts_prefix = 'proxmox_'
inventory.strict = False
inventory.exclude_nodes = False

opts = {
'group_prefix': 'proxmox_',
'facts_prefix': 'proxmox_',
'want_facts': True,
'want_proxmox_nodes_ansible_host': True,
'qemu_extended_statuses': True
'qemu_extended_statuses': True,
'exclude_nodes': False
}

# bypass authentication and API fetch calls
Expand Down Expand Up @@ -723,13 +725,15 @@ def test_populate_missing_qemu_extended_groups(inventory, mocker):
inventory.group_prefix = 'proxmox_'
inventory.facts_prefix = 'proxmox_'
inventory.strict = False
inventory.exclude_nodes = False

opts = {
'group_prefix': 'proxmox_',
'facts_prefix': 'proxmox_',
'want_facts': True,
'want_proxmox_nodes_ansible_host': True,
'qemu_extended_statuses': False
'qemu_extended_statuses': False,
'exclude_nodes': False
}

# bypass authentication and API fetch calls
Expand All @@ -743,3 +747,40 @@ def test_populate_missing_qemu_extended_groups(inventory, mocker):
# make sure that ['prelaunch', 'paused'] are not in the group list
for group in ['paused', 'prelaunch']:
assert ('%sall_%s' % (inventory.group_prefix, group)) not in inventory.inventory.groups


def test_populate_exclude_nodes(inventory, mocker):
# module settings
inventory.proxmox_user = 'root@pam'
inventory.proxmox_password = 'password'
inventory.proxmox_url = 'https://localhost:8006'
inventory.group_prefix = 'proxmox_'
inventory.facts_prefix = 'proxmox_'
inventory.strict = False
inventory.exclude_nodes = True

opts = {
'group_prefix': 'proxmox_',
'facts_prefix': 'proxmox_',
'want_facts': True,
'want_proxmox_nodes_ansible_host': True,
'qemu_extended_statuses': False,
'exclude_nodes': True
}

# bypass authentication and API fetch calls
inventory._get_auth = mocker.MagicMock(side_effect=get_auth)
inventory._get_json = mocker.MagicMock(side_effect=get_json)
inventory._get_vm_snapshots = mocker.MagicMock(side_effect=get_vm_snapshots)
inventory.get_option = mocker.MagicMock(side_effect=get_option(opts))
inventory._can_add_host = mocker.MagicMock(return_value=True)
inventory._populate()

# make sure that nodes are not in the inventory
for node in ['testnode', 'testnode2']:
assert node not in inventory.inventory.hosts
# make sure that nodes group is absent
assert ('%s_nodes' % (inventory.group_prefix)) not in inventory.inventory.groups
# make sure that nodes are not in the "ungrouped" group
for node in ['testnode', 'testnode2']:
assert node not in inventory.inventory.get_groups_dict()["ungrouped"]

0 comments on commit d05932f

Please sign in to comment.