Ansible YAML Inventory Builder
Project Overview
This interactive Python script simplifies creating valid Ansible YAML inventories, especially in
airgapped environments. It guides you through defining groups, hosts (supporting formats like
hostname=ip, hostname-only, or IP-only), and optional child groups. The output is clean,
Ansible-compliant YAML ready for immediate use with ansible or
ansible-playbook commands.
Built quickly with GenAI assistance—perfect for labs, automation pipelines, or teaching Ansible basics. It eliminates manual YAML errors and enforces best practices.
- Requirements: Python 3 with PyYAML (install via
pip install pyyamlif needed). - Usage: Run
python3 yml-create.py(or with--output filename.ymlto skip prompt). - Features: Input validation, child group checks, sorted output, and built-in preview.
Full Code
Security Note: Always review code before executing. SHA256 Hash: 51ea38c9041b22416e305b7abeb27ccf8d0ebc13c2d71b424a6cc7dd6c039a30/p>
import argparse
import sys
import yaml
def main():
parser = argparse.ArgumentParser(
description="Interactively build an Ansible YAML inventory (official format)."
)
parser.add_argument(
"--output",
default=None,
help="Output file for the inventory (skips filename prompt)"
)
args = parser.parse_args()
# Internal structure:
# groupname: {
# 'hosts': {hostname: {vars}},
# 'children': set()
# }
groups = {}
print("\nInteractive Ansible YAML Inventory Builder")
print("Rules:")
print("- Top-level keys are group names")
print("- Hosts may be 'hostname=ip', hostname-only, or ip-only")
print("- Child groups are optional\n")
while True:
group_name = input("Enter group name (or 'done' to finish): ").strip()
if group_name.lower() == "done":
break
if not group_name:
print("Group name cannot be empty.\n")
continue
group = groups.setdefault(
group_name,
{"hosts": {}, "children": set()}
)
hosts_input = input(
f"Hosts for '{group_name}' "
"(comma-separated, empty for none): "
).strip()
if hosts_input:
for item in hosts_input.split(","):
item = item.strip()
if not item:
continue
# hostname=ip format
if "=" in item:
hostname, addr = item.split("=", 1)
hostname = hostname.strip()
addr = addr.strip()
if not hostname or not addr:
print(f"Ignoring invalid host entry: {item}")
continue
group["hosts"][hostname] = {
"ansible_host": addr
}
else:
# hostname-only OR ip-only
group["hosts"][item] = {}
children_input = input(
f"Child groups for '{group_name}' "
"(comma-separated, empty for none): "
).strip()
if children_input:
for child in children_input.split(","):
child = child.strip()
if not child:
continue
if child == group_name:
print("A group cannot be its own child — ignored.")
else:
group["children"].add(child)
print()
if not groups:
print("No groups defined. Exiting.")
sys.exit(0)
# Validate referenced children
defined_groups = set(groups.keys())
undefined_children = {
child
for g in groups.values()
for child in g["children"]
if child not in defined_groups
}
if undefined_children:
print("\nWarning: These child groups are referenced but not defined:")
for name in sorted(undefined_children):
print(f" - {name}")
if input("Proceed anyway? (y/n): ").strip().lower() != "y":
print("Aborted.")
sys.exit(1)
# Build final inventory
inventory = {}
for group_name in sorted(groups):
data = groups[group_name]
entry = {}
# Hosts (always emitted)
entry["hosts"] = dict(sorted(data["hosts"].items()))
# Children (only if defined)
if data["children"]:
entry["children"] = {child: {} for child in sorted(data["children"])}
inventory[group_name] = entry
# Output filename
if args.output:
output_file = args.output
else:
while True:
output_file = input("Output filename (inventory.yml): ").strip()
if output_file:
break
# Write YAML
try:
with open(output_file, "w") as f:
yaml.safe_dump(
inventory,
f,
indent=2,
sort_keys=False,
default_flow_style=False
)
except Exception as e:
print(f"Error writing file: {e}")
sys.exit(1)
print(f"\nInventory written to {output_file}\n")
print("Preview:")
print("-" * 40)
with open(output_file) as f:
print(f.read())
if __name__ == "__main__":
main()
Execution Demo
Running the script and generating an inventory:
Verifying the generated inventory with Ansible:
Conclusion
This lightweight tool makes Ansible inventory creation fast, error-free, and repeatable—ideal for
airgapped setups or quick prototyping. Save as yml-create.py, make executable if desired,
and start building inventories effortlessly.