diff --git a/awx/api/serializers.py b/awx/api/serializers.py index d7e0e90066..05bcfa9ed2 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1793,14 +1793,22 @@ class ConstructedInventorySerializer(InventorySerializer): allow_blank=True, help_text=_('The limit to restrict the returned hosts for the related auto-created inventory source, special to constructed inventory.'), ) + verbosity = ConstructedIntegerField( + required=False, + allow_null=True, + min_value=0, + max_value=2, + default=None, + help_text=_('The verbosity level for the related auto-created inventory source, special to constructed inventory'), + ) class Meta: model = Inventory - fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit') + fields = ('*', '-host_filter', 'source_vars', 'update_cache_timeout', 'limit', 'verbosity') def pop_inv_src_data(self, data): inv_src_data = {} - for field in ('source_vars', 'update_cache_timeout', 'limit'): + for field in ('source_vars', 'update_cache_timeout', 'limit', 'verbosity'): if field in data: # values always need to be removed, as they are not valid for Inventory model value = data.pop(field) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index b958010f4c..964d64f925 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -445,7 +445,7 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): """ if self.kind == 'constructed': if not self.inventory_sources.exists(): - self.inventory_sources.create(source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True) + self.inventory_sources.create(source='constructed', name=f'Auto-created source for: {self.name}'[:512], overwrite=True, update_on_launch=True) def save(self, *args, **kwargs): self._update_host_smart_inventory_memeberships() diff --git a/docs/inventory/inventory_refresh.md b/docs/deprecated/inventory_refresh.md similarity index 100% rename from docs/inventory/inventory_refresh.md rename to docs/deprecated/inventory_refresh.md diff --git a/docs/inventory/constructed_inventory.md b/docs/inventory/constructed_inventory.md new file mode 100644 index 0000000000..8516723fe3 --- /dev/null +++ b/docs/inventory/constructed_inventory.md @@ -0,0 +1,86 @@ +### Constructed inventory in AWX + +Constructed inventory is a separate "kind" of inventory, along-side of +normal (manual) inventories and "smart" inventories. +The functionality overlaps with smart inventory, and it is intended that +smart inventory is sunsetted and will be eventually removed. + +#### Demo Problem + +This is branched from original demo at: + +https://github.com/AlanCoding/Ansible-inventory-file-examples/tree/master/issues/AWX371 + +Consider that we have 2 original "source" inventories named "East" and "West". + +``` +# East inventory original contents +host1 account_alias=product_dev +host2 account_alias=product_dev state=shutdown +host3 account_alias=sustaining +``` + +``` +# West inventory original contents +host4 account_alias=product_dev +host6 account_alias=product_dev state=shutdown +host5 account_alias=sustaining state=shutdown +``` + +The user's intent is to operate on _shutdown_ hosts in the _product_dev_ group. +So these are two AND conditions that we want to filter on. + +To accomplish this, the user will create a constructed inventory with +the following properties. + +`source_vars` = + +```yaml +plugin: constructed +strict: true +use_vars_plugins: true # https://github.com/ansible/ansible/issues/75365 +groups: + shutdown: resolved_state == "shutdown" + shutdown_in_product_dev: resolved_state == "shutdown" and account_alias == "product_dev" +compose: + resolved_state: state | default("running") +``` + +`limit` = "shutdown_in_product_dev" + +Then when running a job template against the constructed inventory, it should +act on host2 and host6, because those are the two hosts that fit the criteria. + +#### Mechanic + +The constructed inventory contents will be materialized by an inventory update +which runs via `ansible-inventory`. +This is always configured to update-on-launch before a job, +but the user can still select a cache timeout value in case this takes too long. + +When creating a constructed inventory, the API enforces that it always has 1 +inventory source associated with it. +All inventory updates have an associated inventory source, and the fields +needed for constructed inventory (`source_vars` and `limit`) are fields +on the inventory source model normally. + +#### Capabilities + +In addition to filtering on hostvars, users will be able to filter based on +facts, which are prepared before the update in the same way as for jobs. + +For filtering on related objects in the database, users will need to use "meta" +vars that are automatically prepared by the server. +These have names such as: + - `awx_inventory_name` + - `awx_inventory_id` + +#### Best Practices + +It is very important to set the `strict` parameter to `True` so that users +can debug problems with their templates, because these can get complicated. +If the template fails to render, users will get an error in the +associated inventory update for that constructed inventory. + +When encountering errors, it may be prudent to increase `verbosity` to get +more details.