mirror of
https://github.com/ansible/awx.git
synced 2026-10-29 22:03:20 -02:30
Keep inventory sources in their inventory's organization
An inventory source copies its inventory's organization only when it is created, and the API can't change it afterwards, so when an inventory moves to another organization its sources stay behind. Inventory updates copy the source's organization, so they are filed under the old organization too, and their execution environment can fall back to the old organization's default. Have Inventory.save bring its sources' organization in line whenever it is saved with organization, which also repairs sources that are already stale the next time their inventory is saved. related #16702 Assisted-by: Claude Opus 5.5 Signed-off-by: Quanah Gibson-Mount <quanah@dropbox.com>
This commit is contained in:
committed by
akus062381
parent
5613b5ac6c
commit
a17a4bc15f
@@ -481,6 +481,11 @@ class Inventory(CommonModelNameNotUnique, RelatedJobsMixin, OpaQueryPathMixin):
|
||||
def save(self, *args, **kwargs):
|
||||
self._update_host_smart_inventory_memeberships()
|
||||
super(Inventory, self).save(*args, **kwargs)
|
||||
update_fields = kwargs.get('update_fields')
|
||||
if update_fields is None or {'organization', 'organization_id'} & set(update_fields):
|
||||
# An inventory source takes its organization from its inventory and can't set its own, so keep it in step
|
||||
# when the inventory moves.
|
||||
self.inventory_sources.exclude(organization_id=self.organization_id).update(organization_id=self.organization_id)
|
||||
if self.kind == 'smart' and 'host_filter' in kwargs.get('update_fields', ['host_filter']) and connection.vendor != 'sqlite':
|
||||
# Minimal update of host_count for smart inventory host filter changes
|
||||
self.update_computed_fields()
|
||||
|
||||
@@ -4,7 +4,7 @@ import pytest
|
||||
from unittest import mock
|
||||
|
||||
# AWX
|
||||
from awx.main.models import Host, Inventory, InventorySource, InventoryUpdate, CredentialType, Credential, Job
|
||||
from awx.main.models import Host, Inventory, InventorySource, InventoryUpdate, CredentialType, Credential, Job, Organization
|
||||
from awx.main.utils.filters import SmartFilter
|
||||
from awx.main.utils.plugins import discover_available_cloud_provider_plugin_names
|
||||
|
||||
@@ -385,3 +385,40 @@ class TestHostManager:
|
||||
# 2 organizations with host of same name only has 1 entry in smart inventory
|
||||
# smart inventory in 1 organization does not include host from another
|
||||
# smart inventory correctly returns hosts in filter in same organization
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestInventorySourceOrganization:
|
||||
"""An inventory source can't set its organization; it follows its inventory's."""
|
||||
|
||||
def test_new_source_takes_inventory_organization(self, inventory):
|
||||
source = inventory.inventory_sources.create(name='source', source='ec2')
|
||||
assert source.organization_id == inventory.organization_id
|
||||
|
||||
def test_moving_inventory_moves_its_sources(self, inventory, inventory_source):
|
||||
other = Organization.objects.create(name='other-org')
|
||||
inventory.organization = other
|
||||
inventory.save()
|
||||
inventory_source.refresh_from_db()
|
||||
assert inventory_source.organization_id == other.id
|
||||
|
||||
def test_inventory_updates_carry_the_new_organization(self, inventory, inventory_source):
|
||||
other = Organization.objects.create(name='other-org')
|
||||
inventory.organization = other
|
||||
inventory.save()
|
||||
inventory_source.refresh_from_db()
|
||||
assert inventory_source.create_unified_job().organization_id == other.id
|
||||
|
||||
def test_save_repairs_a_source_left_behind(self, inventory, inventory_source):
|
||||
other = Organization.objects.create(name='other-org')
|
||||
InventorySource.objects.filter(pk=inventory_source.pk).update(organization=other)
|
||||
inventory.save()
|
||||
inventory_source.refresh_from_db()
|
||||
assert inventory_source.organization_id == inventory.organization_id
|
||||
|
||||
def test_partial_save_without_organization_leaves_sources_alone(self, inventory, inventory_source):
|
||||
other = Organization.objects.create(name='other-org')
|
||||
InventorySource.objects.filter(pk=inventory_source.pk).update(organization=other)
|
||||
inventory.save(update_fields=['description'])
|
||||
inventory_source.refresh_from_db()
|
||||
assert inventory_source.organization_id == other.id
|
||||
|
||||
Reference in New Issue
Block a user