74 lines
2.1 KiB
Python
74 lines
2.1 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
|
|||
|
|
import json
|
|||
|
|
import subprocess
|
|||
|
|
import os
|
|||
|
|
import yaml
|
|||
|
|
from collections import defaultdict
|
|||
|
|
|
|||
|
|
def get_pulumi_outputs():
|
|||
|
|
output = subprocess.check_output(["pulumi", "stack", "output", "--json"])
|
|||
|
|
return json.loads(output)
|
|||
|
|
|
|||
|
|
def merge_instance_config(config_dir="config"):
|
|||
|
|
merged = {}
|
|||
|
|
for fname in os.listdir(config_dir):
|
|||
|
|
if fname.endswith(".yaml"):
|
|||
|
|
with open(os.path.join(config_dir, fname)) as f:
|
|||
|
|
data = yaml.safe_load(f)
|
|||
|
|
if isinstance(data, dict):
|
|||
|
|
merged.update(data)
|
|||
|
|
return merged.get("instances", [])
|
|||
|
|
|
|||
|
|
def build_inventory(pulumi_outputs, instance_cfgs):
|
|||
|
|
inventory = {"_meta": {"hostvars": {}}}
|
|||
|
|
groups = defaultdict(list)
|
|||
|
|
|
|||
|
|
for inst in instance_cfgs:
|
|||
|
|
name = inst["name"]
|
|||
|
|
public_ip = pulumi_outputs.get(f"{name}_ip")
|
|||
|
|
|
|||
|
|
if not public_ip:
|
|||
|
|
continue # skip not created instances
|
|||
|
|
|
|||
|
|
# 默认分组:all
|
|||
|
|
groups["all"].append(name)
|
|||
|
|
|
|||
|
|
# 根据 subnet 或 lifecycle 添加分组
|
|||
|
|
if "subnet" in inst:
|
|||
|
|
groups[inst["subnet"]].append(name)
|
|||
|
|
if "lifecycle" in inst:
|
|||
|
|
groups[inst["lifecycle"]].append(name)
|
|||
|
|
|
|||
|
|
# hostvars
|
|||
|
|
inventory["_meta"]["hostvars"][name] = {
|
|||
|
|
"ansible_host": public_ip,
|
|||
|
|
"ansible_user": "ubuntu",
|
|||
|
|
"instance_type": inst.get("type"),
|
|||
|
|
"ttl": inst.get("ttl", "none"),
|
|||
|
|
"lifecycle": inst.get("lifecycle", "ondemand"),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 将分组注入 inventory
|
|||
|
|
for group, hosts in groups.items():
|
|||
|
|
inventory[group] = {"hosts": hosts}
|
|||
|
|
|
|||
|
|
return inventory
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
import argparse
|
|||
|
|
parser = argparse.ArgumentParser()
|
|||
|
|
parser.add_argument('--list', action='store_true')
|
|||
|
|
args = parser.parse_args()
|
|||
|
|
|
|||
|
|
if args.list:
|
|||
|
|
pulumi_data = get_pulumi_outputs()
|
|||
|
|
instance_cfgs = merge_instance_config()
|
|||
|
|
inventory = build_inventory(pulumi_data, instance_cfgs)
|
|||
|
|
print(json.dumps(inventory, indent=2))
|
|||
|
|
else:
|
|||
|
|
print(json.dumps({}))
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|