Introduction
Ansible dynamic inventory plugins allow automatic discovery of hosts from cloud providers like AWS, Azure, and GCP. When these plugins fail, Ansible cannot find any hosts to manage, blocking all automation. The failure can occur at multiple points: authentication with the cloud provider, network connectivity, plugin configuration errors, missing dependencies, or API rate limiting.
This issue commonly occurs after: - Cloud credential rotation or expiration - Changes to IAM policies or permissions - Migration between cloud accounts or regions - Upgrading Ansible or cloud provider SDKs - Network changes affecting API access
Symptoms
When running dynamic inventory:
$ ansible-inventory -i aws_ec2.yml --list
[WARNING]: * Failed to parse aws_ec2.yml with auto plugin: botocore.exceptions.NoCredentialsError: Unable to locate credentials
[WARNING]: * Failed to parse aws_ec2.yml with yaml plugin: Plugin configuration YAML failed to find plugin: aws_ec2
[WARNING]: Unable to parse aws_ec2.yml as an inventory source
ERROR! No inventory was parsed, please check your configuration and provide a valid inventory source.Azure inventory errors:
$ ansible-inventory -i azure_rm.yml --list
ERROR! Unexpected Exception, this is probably a bug: msrest.exceptions.AuthenticationError: Authentication failed.
- AADSTS700016: Application with identifier 'xxx' was not found in the directoryGCP inventory errors:
$ ansible-inventory -i gcp_compute.yml --list
ERROR! Unexpected Exception, this is probably a bug: google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found.Plugin configuration errors:
$ ansible-inventory -i inventory/aws_ec2.yml --list
[WARNING]: * Failed to parse inventory/aws_ec2.yml with aws_ec2 plugin: 'regions'
[WARNING]: * Failed to parse inventory/aws_ec2.yml with yaml plugin: Plugin configuration YAML failed to find plugin: aws_ec2Empty inventory returned:
$ ansible-inventory -i aws_ec2.yml --graph
@all:
|--@ungrouped:
# No hosts returned despite instances running in cloudAPI rate limiting:
$ ansible-inventory -i aws_ec2.yml --list
ERROR! Unexpected Exception: botocore.exceptions.ClientError: An error occurred (RequestLimitExceeded) when calling the DescribeInstances operation: Request limit exceeded.Common Causes
1. Missing or Invalid Cloud Provider Credentials
AWS credentials not configured:
$ aws sts get-caller-identity
Unable to locate credentials. You can configure credentials by running "aws configure".Azure credentials expired:
$ az account show
ERROR: Please run 'az login' to setup account.2. Incorrect Python Dependencies
Required SDK not installed:
$ python3 -c "import boto3"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'boto3'3. Plugin Configuration Errors
Wrong plugin name or structure:
```yaml # Wrong - old-style script name plugin: ec2.py # Should be 'aws_ec2'
# Wrong - missing required parameters plugin: aws_ec2 # Missing 'regions' parameter ```
4. IAM Permission Issues
Missing permissions to list instances:
{
"errorCode": "UnauthorizedOperation",
"message": "You are not authorized to perform this operation.",
"statusCode": 403
}5. Network Connectivity Issues
Cannot reach cloud API:
$ curl -I https://ec2.us-east-1.amazonaws.com
curl: (6) Could not resolve host: ec2.us-east-1.amazonaws.com6. Cache Issues
Stale cache returning old inventory:
$ ls -la ~/.ansible/tmp/ansible-inventory-cache/
# Old cache files with incorrect dataStep-by-Step Fix
Step 1: Diagnose the Inventory Plugin Failure
Test the inventory plugin directly:
```bash # Test with verbose output ansible-inventory -i aws_ec2.yml --list -vvv 2>&1 | head -100
# Check if plugin is recognized ansible-doc -t inventory aws_ec2
# Verify plugin can be loaded python3 -c "from ansible.plugins.inventory.aws_ec2 import InventoryModule; print('Plugin OK')" ```
Check installed Ansible version and collections:
ansible --version
ansible-galaxy collection list | grep amazon
# Required: amazon.aws >= 5.0.0 for aws_ec2 pluginStep 2: Fix Cloud Provider Authentication
For AWS:
```bash # Check current credentials aws sts get-caller-identity
# If not configured, set up credentials aws configure # Or export environment variables export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY export AWS_DEFAULT_REGION=us-east-1
# Or use IAM role (preferred for EC2) # No credentials needed if running on EC2 with IAM role
# Test AWS access aws ec2 describe-instances --region us-east-1 --query 'Reservations[].Instances[].InstanceId' ```
For Azure:
```bash # Login to Azure az login
# Or use service principal az login --service-principal -u APP_ID -p PASSWORD --tenant TENANT_ID
# Set subscription az account set --subscription SUBSCRIPTION_ID
# Verify access az vm list --query '[].name' -o tsv ```
For GCP:
```bash # Authenticate with GCP gcloud auth login
# Or use service account export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
# Verify access gcloud compute instances list ```
Step 3: Install Required Python Dependencies
```bash # For AWS pip install boto3 botocore
# For Azure pip install azure-cli azure-mgmt-compute azure-mgmt-network azure-mgmt-resource msrestazure
# For GCP pip install google-api-python-client google-auth google-auth-httplib2
# Verify installations python3 -c "import boto3; print('boto3:', boto3.__version__)" python3 -c "import azure.mgmt.compute; print('azure-mgmt-compute OK')" python3 -c "import google.auth; print('google-auth OK')" ```
Step 4: Fix Plugin Configuration
Correct AWS EC2 inventory configuration:
```yaml # aws_ec2.yml plugin: aws_ec2 regions: - us-east-1 - us-west-2
# Authentication (if not using environment/IAM role) # aws_access_key: "{{ lookup('env', 'AWS_ACCESS_KEY_ID') }}" # aws_secret_key: "{{ lookup('env', 'AWS_SECRET_ACCESS_KEY') }}"
# Filter instances filters: instance-state-name: running tag:Environment: production
# Group instances by tags keyed_groups: - key: tags.Environment prefix: env - key: tags.Role prefix: role - key: placement.region prefix: region
# Include host variables compose: ansible_host: public_ip_address private_ip: private_ip_address ```
Correct Azure RM inventory configuration:
```yaml # azure_rm.yml plugin: azure_rm auth_source: auto # auto, cli, credential_file, env, msi
# Subscription filter subscription_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# Include specific resource groups resource_groups: - production-rg - staging-rg
# Group by tags keyed_groups: - prefix: tag key: tags - prefix: location key: location
# Host variable composition compose: ansible_host: public_ip_address | default(private_ip_address) conditional_groups: webservers: "'web' in tags.Role" databases: "'db' in tags.Role" ```
Correct GCP Compute inventory configuration:
```yaml # gcp_compute.yml plugin: gcp_compute projects: - my-project-id zones: - us-central1-a - us-east1-b
filters: - status = RUNNING
# Service account authentication auth_kind: serviceaccount service_account_file: /path/to/service-account.json
# Group by labels keyed_groups: - key: labels.role prefix: role - key: zone prefix: zone
compose: ansible_host: networkInterfaces[0].accessConfigs[0].natIP ```
Step 5: Fix IAM Permissions
Required AWS IAM policy for EC2 inventory:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeRegions",
"ec2:DescribeTags"
],
"Resource": "*"
}
]
}Required Azure role for inventory:
# Assign Reader role at subscription level
az role assignment create \
--assignee SERVICE_PRINCIPAL_ID \
--role Reader \
--scope /subscriptions/SUBSCRIPTION_IDStep 6: Fix Cache Issues
Clear stale inventory cache:
```bash # Clear Ansible fact cache rm -rf ~/.ansible/tmp/ansible-facts-cache/ rm -rf ~/.ansible/tmp/ansible-inventory-cache/
# Or use the cache plugin settings in ansible.cfg [defaults] fact_caching = memory inventory_cache = false inventory_cache_connection = ~/.ansible/tmp/inventory_cache inventory_cache_timeout = 300
# Force refresh of dynamic inventory ansible-inventory -i aws_ec2.yml --list --refresh ```
Step 7: Test Inventory Connectivity
Create a test playbook:
```yaml # test_inventory.yml - name: Test dynamic inventory hosts: localhost connection: local gather_facts: false vars: inventory_file: aws_ec2.yml
tasks: - name: Load inventory command: ansible-inventory -i {{ inventory_file }} --list register: inventory_output changed_when: false
- name: Parse inventory
- set_fact:
- loaded_inventory: "{{ inventory_output.stdout | from_json }}"
- name: Display inventory summary
- debug:
- msg:
- - "Total hosts: {{ loaded_inventory._meta.hostvars | length }}"
- - "Groups: {{ loaded_inventory.keys() | list }}"
- name: Test connectivity to all hosts
- ansible.builtin.ping:
- delegate_to: "{{ item }}"
- loop: "{{ loaded_inventory._meta.hostvars.keys() | list }}"
`
Run the test:
ansible-playbook test_inventory.yml -e "inventory_file=aws_ec2.yml"Verification
Test inventory retrieval:
```bash # List all hosts ansible-inventory -i aws_ec2.yml --list | jq '._meta.hostvars | keys'
# Show inventory graph ansible-inventory -i aws_ec2.yml --graph
# Test connectivity to discovered hosts ansible all -i aws_ec2.yml -m ping
# Show host variables ansible-inventory -i aws_ec2.yml --host i-1234567890abcdef0 ```
Verify authentication:
```bash # AWS aws sts get-caller-identity aws ec2 describe-instances --query 'length(Reservations)'
# Azure az account show az vm list --query 'length([])'
# GCP gcloud auth list gcloud compute instances list --format="value(name)" ```
Test inventory in playbook:
```bash # Run a simple playbook against dynamic inventory ansible all -i aws_ec2.yml -m setup -a "filter=ansible_hostname"
# Should return hostnames for all discovered instances ```
Related Issues
- [ansible-credential-timeout](/articles/ansible-credential-timeout)
- [ansible-api-rate-limiting](/articles/ansible-api-rate-limiting)
- [ansible-inventory-cache-stale](/articles/ansible-inventory-cache-stale)
Related Articles
- [WordPress troubleshooting: Ansible Artifact Download Uses an Old Mi](ansible-artifact-download-uses-an-old-mirror-after-proxy-change)
- [WordPress troubleshooting: Ansible Audit Trail Misses Events Under ](ansible-audit-trail-misses-events-under-burst-load)
- [WordPress troubleshooting: Ansible Background Worker Gets Stuck in ](ansible-background-worker-stuck-in-a-retry-loop)
- [WordPress troubleshooting: Ansible Backup Completes but Restore Fai](ansible-backup-completes-but-restore-fails-checksum-validation)
- [WordPress troubleshooting: Ansible Batch Importer Duplicates Rows A](ansible-batch-importer-duplicates-rows-after-a-retry)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "WordPress troubleshooting: Ansible Dynamic Inventory from Cloud Sou", "description": "Learn how to fix Ansible Dynamic Inventory from Cloud Source Failed. Professional WordPress troubleshooting solutions with step-by-step guidance. WP error fix, WordPress optimization, WP security, WordPress performance.", "url": "https://www.fixwikihub.com/ansible-inventory-dynamic-cloud-source-failed", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-12-15T15:12:18.594Z", "dateModified": "2025-12-15T15:12:18.594Z" } </script>