Builds an inventory from resources created by cloud providers.
Version added: 2.1.0
- This plugin works with an existing state file to create an inventory from resources created by cloud providers.
- The plugin accepts a Terraform backend config to an existing state file or a path to an existing state file.
- Uses a YAML configuration file that ends with terraform_state.(yml|yaml).
- To read the state file command
Terraform show
is used. - Does not support caching.
Parameter | Choices/Defaults | Configuration | Comments | |
---|---|---|---|---|
backend_config
dictionary
|
A group of key-values used to configure the backend.
These values will be provided at init stage to the -backend-config parameter.
|
|||
backend_config_files
list
/ elements=path
|
The absolute path to a configuration file to provide at init state to the -backend-config parameter. This can accept a list of paths to multiple configuration files.
|
|||
backend_type
string
/ required
|
The Terraform backend type from which the state file will be retrieved.
|
|||
binary_path
path
|
The path of a terraform binary to use.
|
|||
compose
dictionary
|
Default: {}
|
Create vars from jinja2 expressions.
|
||
groups
dictionary
|
Default: {}
|
Add hosts to group based on Jinja2 conditionals.
|
||
hostnames
list
/ elements=raw
|
Default: []
|
A list in order of precedence for hostname variables.
The elements of the list can be a dict with the keys mentioned below or a string.
Can be one of the options specified in https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#argument-reference.
If value provided does not exist in the above options, it will be used as a literal string.
To use tags as hostnames use the syntax tag:Name=Value to use the hostname Name_Value, or tag:Name to use the value of the Name tag.
If not provided the final hostname will be
terraform resource type + _ + terraform resource name |
||
name
string
/ required
|
Name of the host.
|
|||
prefix
string
|
Default: ""
|
Prefix to prepend to name. Same options as name.
If prefix is specified, final hostname will be prefix + separator + name.
|
||
separator
string
|
Default: "_"
|
Value to separate prefix and name when prefix is specified.
|
||
keyed_groups
list
/ elements=dictionary
|
Default: []
|
Add hosts to group based on the values of a variable.
|
||
default_value
string
added in 2.12
|
The default value when the host variable's value is an empty string.
This option is mutually exclusive with O(keyed_groups[].trailing_separator).
|
|||
key
string
|
The key from input dictionary used to generate groups
|
|||
parent_group
string
|
parent group for keyed group
|
|||
prefix
string
|
Default: ""
|
A keyed group name will start with this prefix
|
||
separator
string
|
Default: "_"
|
separator used to build the keyed group name
|
||
trailing_separator
boolean
added in 2.12
|
|
Set this option to V(False) to omit the O(keyed_groups[].separator) after the host variable when the value is an empty string.
This option is mutually exclusive with O(keyed_groups[].default_value).
|
||
leading_separator
boolean
added in 2.11
|
Default: "yes"
|
Use in conjunction with keyed_groups.
By default, a keyed group that does not have a prefix or a separator provided will have a name that starts with an underscore.
This is because the default prefix is "" and the default separator is "_".
Set this option to False to omit the leading underscore (or other separator) if no prefix is given.
If the group name is derived from a mapping the separator is still used to concatenate the items.
To not use a separator in the group name at all, set the separator for the keyed group to an empty string instead.
|
||
plugin
string
/ required
|
|
The name of the Inventory Plugin.
This should always be
cloud.terraform.terraform_state . |
||
search_child_modules
boolean
|
|
Whether to include resources from Terraform child modules.
|
||
strict
boolean
|
|
If V(yes) make invalid entries a fatal error, otherwise skip and continue.
Since it is possible to use facts in the expressions they might not always be available and we ignore those errors by default.
|
||
use_extra_vars
boolean
added in 2.11
|
|
ini entries:
[inventory_plugins] env:ANSIBLE_INVENTORY_USE_EXTRA_VARS
|
Merge extra vars into the available variables for composition (highest precedence).
|
# Inventory with state file stored into http backend
- name: Create an inventory from state file stored into http backend
plugin: cloud.terraform.terraform_state
backend_type: http
backend_config:
address: https://localhost:8043/api/v2/state/3/
skip_cert_verification: true
username: ansible
password: test123!
# Running command `ansible-inventory -i basic_terraform_state.yaml --graph --vars` would then produce the inventory:
# @all:
# |--@ungrouped:
# | |--aws_instance_test
# | | |--{ami = ami-01d00f1bdb42735ac}
# | | |--{arn = arn:aws:ec2:us-east-1:721066863947:instance/i-09c4a5b5d74c9b941}
# | | |--{associate_public_ip_address = True}
# | | |--{availability_zone = us-east-1b}
# | | |--{capacity_reservation_specification = [{'capacity_reservation_preference': 'open', 'capacity_reservation_target': []}]}
# | | |--{cpu_core_count = 1}
# | | |--{cpu_options = [{'amd_sev_snp': '', 'core_count': 1, 'threads_per_core': 1}]}
# | | |--{cpu_threads_per_core = 1}
# | | |--{credit_specification = [{'cpu_credits': 'standard'}]}
# | | |--{disable_api_stop = False}
# | | |--{disable_api_termination = False}
# | | |--{ebs_block_device = []}
# | | |--{ebs_optimized = False}
# | | |--{enclave_options = [{'enabled': False}]}
# | | |--{ephemeral_block_device = []}
# | | |--{get_password_data = False}
# | | |--{hibernation = False}
# | | |--{host_id = }
# | | |--{host_resource_group_arn = None}
# | | |--{iam_instance_profile = }
# | | |--{id = i-09c4a5b5d74c9b941}
# | | |--{instance_initiated_shutdown_behavior = stop}
# | | |--{instance_lifecycle = }
# | | |--{instance_market_options = []}
# | | |--{instance_state = running}
# | | |--{instance_type = t2.micro}
# | | |--{ipv6_address_count = 0}
# | | |--{ipv6_addresses = []}
# | | |--{key_name = connect-key-20231127}
# | | |--{launch_template = []}
# | | |--{maintenance_options = [{'auto_recovery': 'default'}]}
# | | |--{metadata_options = [{...}]}
# | | |--{monitoring = False}
# | | |--{network_interface = []}
# | | |--{outpost_arn = }
# | | |--{password_data = }
# | | |--{placement_group = }
# | | |--{placement_partition_number = 0}
# | | |--{primary_network_interface_id = eni-0d5ccb55032b5e01c}
# | | |--{private_dns = ip-168-10-1-178.us-east-1.compute.internal}
# | | |--{private_dns_name_options = [{...}]}
# | | |--{private_ip = 168.10.1.178}
# | | |--{public_dns = }
# | | |--{public_ip = 34.244.225.201}
# | | |--{root_block_device = [{...}]}
# | | |--{secondary_private_ips = []}
# | | |--{security_groups = []}
# | | |--{source_dest_check = True}
# | | |--{spot_instance_request_id = }
# | | |--{subnet_id = subnet-0e5159474f5fc6a17}
# | | |--{tags = {'Inventory': 'terraform_state', 'Name': 'test-ec2', 'Phase': 'integration'}}
# | | |--{tags_all = {'Inventory': 'terraform_state', 'Name': 'test-ec2', 'Phase': 'integration'}}
# | | |--{tenancy = default}
# | | |--{timeouts = None}
# | | |--{user_data = None}
# | | |--{user_data_base64 = None}
# | | |--{user_data_replace_on_change = False}
# | | |--{volume_tags = None}
# | | |--{vpc_security_group_ids = ['sg-0795c8f75883b0927']}
# Example using constructed features to set ansible_host
- name: Using compose feature to set the ansible_host
plugin: cloud.terraform.terraform_state
backend_type: s3
backend_config:
region: us-east-1
key: terraform/state
bucket: my-sample-bucket
compose:
ansible_host: public_ip
# Running command `ansible-inventory -i compose_terraform_state.yaml --graph --vars` would then produce the inventory:
# @all:
# |--@ungrouped:
# | |--aws_instance_test
# | | |--{ami = ami-01d00f1bdb42735ac}
# | | |--{ansible_host = 34.244.225.201}
# (...)
# | | |--{public_ip = 34.244.225.201}
# (...)
# Example using constructed features to create inventory groups
- name: Using keyed_groups feature to add host into group
plugin: cloud.terraform.terraform_state
backend_type: s3
backend_config:
region: us-east-1
key: terraform/state
bucket: my-sample-bucket
keyed_groups:
- key: instance_state
prefix: state
# Running command `ansible-inventory -i keyed_terraform_state.yaml --graph` would then produce the inventory:
# @all:
# |--@ungrouped:
# |--@state_running:
# | |--aws_instance_test
# Example using hostnames feature to define inventory hostname
- name: Using hostnames feature to define inventory hostname
plugin: cloud.terraform.terraform_state
backend_type: s3
backend_config:
region: us-east-1
key: terraform/state
bucket: my-sample-bucket
hostnames:
- name: 'tag:Phase'
separator: "-"
prefix: 'instance_state'
# Running command `ansible-inventory -i hostnames_terraform_state.yaml --graph` would then produce the inventory:
# @all:
# |--@ungrouped:
# | |--running-integration
# Example using backend_config_files option to configure the backend
- name: Using backend_config_files to configure the backend
plugin: cloud.terraform.terraform_state
backend_type: s3
backend_config:
region: us-east-1
backend_config_files:
- /path/to/config1
- /path/to/config2
# With the following content for config1
#
# key = "terraform/tfstate"
# bucket = "my-tf-backend-bucket"
#
# and the following content for config2
#
# access_key = "xxxxxxxxxxxxxx"
# secret_key = "xxxxxxxxxxxxxx"
# token = "xxxxxxxxxxxxx"
# Inventory built from state file containing AWS, AzureRM and GCP instances
- name: Create inventory from state file containing AWS, AzureRM and GCP instances
plugin: cloud.terraform.terraform_state
backend_type: azurerm
backend_config:
resource_group_name: my-resource-group
storage_account_name: mystorageaccount
container_name: terraformstate
key: inventory.tfstate
# Running command `ansible-inventory -i aws_and_azure_terraform_state.yaml --graph --vars` would then produce the inventory:
# @all:
# |--@ungrouped:
# | |--aws_instance_test
# | | |--{ami = ami-01d00f1bdb42735ac}
# | | |--{arn = arn:aws:ec2:us-east-1:721066863947:instance/i-09c4a5b5d74c9b941}
# | | |--{associate_public_ip_address = True}
# | | |--{availability_zone = us-east-1b}
# | | |--{capacity_reservation_specification = [{'capacity_reservation_preference': 'open', 'capacity_reservation_target': []}]}
# | | |--{cpu_core_count = 1}
# | | |--{cpu_options = [{'amd_sev_snp': '', 'core_count': 1, 'threads_per_core': 1}]}
# | | |--{cpu_threads_per_core = 1}
# | | |--{credit_specification = [{'cpu_credits': 'standard'}]}
# | | |--{disable_api_stop = False}
# | | |--{disable_api_termination = False}
# | | |--{ebs_block_device = []}
# | | |--{ebs_optimized = False}
# | | |--{enclave_options = [{'enabled': False}]}
# | | |--{ephemeral_block_device = []}
# | | |--{get_password_data = False}
# | | |--{hibernation = False}
# | | |--{host_id = }
# | | |--{host_resource_group_arn = None}
# | | |--{iam_instance_profile = }
# | | |--{id = i-09c4a5b5d74c9b941}
# | | |--{instance_initiated_shutdown_behavior = stop}
# | | |--{instance_lifecycle = }
# | | |--{instance_market_options = []}
# | | |--{instance_state = running}
# | | |--{instance_type = t2.micro}
# | | |--{ipv6_address_count = 0}
# | | |--{ipv6_addresses = []}
# | | |--{key_name = connect-key-20231127}
# | | |--{launch_template = []}
# | | |--{maintenance_options = [{'auto_recovery': 'default'}]}
# | | |--{metadata_options = [{...}]}
# | | |--{monitoring = False}
# | | |--{network_interface = []}
# | | |--{outpost_arn = }
# | | |--{password_data = }
# | | |--{placement_group = }
# | | |--{placement_partition_number = 0}
# | | |--{primary_network_interface_id = eni-0d5ccb55032b5e01c}
# | | |--{private_dns = ip-168-10-1-178.us-east-1.compute.internal}
# | | |--{private_dns_name_options = [{...}]}
# | | |--{private_ip = 168.10.1.178}
# | | |--{public_dns = }
# | | |--{public_ip = 34.244.225.201}
# | | |--{root_block_device = [{...}]}
# | | |--{secondary_private_ips = []}
# | | |--{security_groups = []}
# | | |--{source_dest_check = True}
# | | |--{spot_instance_request_id = }
# | | |--{subnet_id = subnet-0e5159474f5fc6a17}
# | | |--{tags = {'Inventory': 'terraform_state', 'Name': 'test-ec2', 'Phase': 'integration'}}
# | | |--{tags_all = {'Inventory': 'terraform_state', 'Name': 'test-ec2', 'Phase': 'integration'}}
# | | |--{tenancy = default}
# | | |--{timeouts = None}
# | | |--{user_data = None}
# | | |--{user_data_base64 = None}
# | | |--{user_data_replace_on_change = False}
# | | |--{volume_tags = None}
# | | |--{vpc_security_group_ids = ['sg-0795c8f75883b0927']}
# | |--azurerm_virtual_machine_main
# | | |--{additional_capabilities = []}
# | | |--{availability_set_id = None}
# | | |--{boot_diagnostics = []}
# | | |--{delete_data_disks_on_termination = True}
# | | |--{delete_os_disk_on_termination = True}
# | | |--{id = /subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxxxx/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/test-vm}
# | | |--{identity = []}
# | | |--{license_type = None}
# | | |--{location = westeurope}
# | | |--{name = test-vm}
# | | |--{network_interface_ids = ['/subscriptions/xxxxx-xxxx-xxxx-xxxx-xxxxxxxx/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/test']}
# | | |--{os_profile = [{'admin_password': '', 'admin_username': 'ansible', 'computer_name': 'hostname', 'custom_data': ''}]}
# | | |--{os_profile_linux_config = [{'disable_password_authentication': False, 'ssh_keys': []}]}
# | | |--{os_profile_secrets = []}
# | | |--{os_profile_windows_config = []}
# | | |--{plan = []}
# | | |--{primary_network_interface_id = None}
# | | |--{proximity_placement_group_id = None}
# | | |--{resource_group_name = rg}
# | | |--{storage_data_disk = []}
# | | |--{storage_image_reference = [{'id': '', 'offer': 'xxxxx', 'publisher': 'Canonical', 'sku': '22_04-lts', 'version': 'latest'}]}
# | | |--{timeouts = None}
# | | |--{vm_size = Standard_DS1_v2}
# | | |--{zones = []}
# | |--google_compute_instance_default
# | | |--{advanced_machine_features = []}
# | | |--{allow_stopping_for_update = None}
# | | |--{attached_disk = []}
# | | |--{boot_disk = [{'auto_delete': True, 'device_name': 'persistent-disk-0', 'disk_encryption_key_raw': ''}]
# | | |--{can_ip_forward = False}
# | | |--{confidential_instance_config = []}
# | | |--{cpu_platform = Intel Cascade Lake}
# | | |--{current_status = RUNNING}
# | | |--{deletion_protection = False}
# | | |--{description = }
# | | |--{desired_status = None}
# | | |--{effective_labels = {}}
# | | |--{enable_display = False}
# | | |--{guest_accelerator = []}
# | | |--{hostname = }
# | | |--{id = projects/xxxx/zones/us-east1-c/instances/ansible-cloud-001}
# | | |--{instance_id = 0123456789012345678}
# | | |--{label_fingerprint = 42WmSpB8rSM=}
# | | |--{labels = {}}
# | | |--{machine_type = n2-standard-2}
# | | |--{metadata = {}}
# | | |--{metadata_fingerprint = WP5-7HGjCUM=}
# | | |--{metadata_startup_script = None}
# | | |--{min_cpu_platform = }
# | | |--{name = ansible-cloud-001}
# | | |--{network_performance_config = []}
# | | |--{params = []}
# | | |--{project = agcp-001-dev}
# | | |--{reservation_affinity = []}
# | | |--{resource_policies = []}
# | | |--{scratch_disk = [{'device_name': 'local-ssd-0', 'interface': 'NVME', 'size': 375}]}
# | | |--{service_account = []}
# | | |--{tags = []}
# | | |--{tags_fingerprint = 42WmSpB8rSM=}
# | | |--{terraform_labels = {}}
# | | |--{timeouts = None}
# | | |--{zone = us-east1-c}
- Aubin Bikouo (@abikouo)
Hint
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.