diff --git a/.gitignore b/.gitignore index 5e778b5c554a04a2d257e3816a54a8941e77dd13..ace00ac8ad581331eced697688888b9bcb69cde3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,11 @@ docs/vale/styles/* venv/ .venv/ +.mypy_cache +.pytest_cache +.ruff_cache +build/ + # Ignore files generated by apidoc docs/source/lso.rst docs/source/lso.*.rst diff --git a/README.md b/README.md index 7f61c0131b2db6771ac43889f408f759f7c76236..5026025e275a6e41d2d107405c6dd55da4dd1084 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,10 @@ Fill in environment variables and run the command to generate the Ansible invent # Rewritting environment variables ## URL of the WFO API (change IP only) export api_url=http://127.0.0.1:8080/api/v1/subscriptions/routers -## Full paths where this tool will save variables and inventory files -export host_vars_dir=/path/to/base/hostvars/dir -export hosts_file_dir=/path/to/base/hosts/dir -## Full path where this tool will save the WFO variables -export vars_file_name=wfo_vars.yaml ## Token provided by each GSO instance admin (varies per environment) export gso_api_key=<fill_with_gso_token> +## Full paths where AIG will save host_vars +export host_vars_dir=/path/to/base/host_vars/dir # Execution of the command to generate the Ansible inventory files ansible_inventory_generator @@ -63,6 +60,4 @@ pip install -U pip setuptools wheel ### 403 error when running the `ansible_inventory_generator` command -This tool cannot reach the WFO API because it is authenticated. -Correct it by redeploying WFO by first running `export OAUTH2_ACTIVE=false` and then re-running WFO. -Alternatively, change `export api_url` to an authenticated instance of GSO. \ No newline at end of file +This tool cannot reach the GSO API because it is authenticated. Use a correct gso_api_key environment variable. diff --git a/ansible_inventory_generator/app.py b/ansible_inventory_generator/app.py index 7b535c2bb502d6fec84aed0f996a3591affffbfb..1591e861b7c8073b40bbeeb64eb80a391e26c561 100644 --- a/ansible_inventory_generator/app.py +++ b/ansible_inventory_generator/app.py @@ -56,7 +56,7 @@ def write_hosts_file(groups: dict, hosts_file: Path) -> None: def generate_host_vars_and_hosts_file(router_subscriptions: list, temp_dir: Path) -> None: """Process router subscriptions data.""" groups: dict[str, list[str]] = {} - host_vars_dir = temp_dir / "hostvars" + host_vars_dir = temp_dir / "host_vars" host_vars_dir.mkdir() for router_subscription in router_subscriptions: @@ -67,7 +67,7 @@ def generate_host_vars_and_hosts_file(router_subscriptions: list, temp_dir: Path write_host_vars(host_name, router, host_vars_dir) - vendor_group = router.get("router_vendor", "").lower() + vendor_group = router.get("vendor", "").lower() role_group = f"{router.get('router_role', '')}_routers" groups.setdefault(vendor_group, []).append(host_name) @@ -78,7 +78,7 @@ def generate_host_vars_and_hosts_file(router_subscriptions: list, temp_dir: Path @contextmanager -def safe_write(temp_dir: Path, old_vars_dir: Path, old_hosts_file: Path) -> Generator[Path, None, None]: +def safe_write(temp_dir: Path, old_host_vars_dir: Path) -> Generator[Path, None, None]: temp_dir.mkdir(exist_ok=True) try: @@ -88,11 +88,11 @@ def safe_write(temp_dir: Path, old_vars_dir: Path, old_hosts_file: Path) -> Gene typer.echo(f"Error: {e}") sys.exit(1) else: - if old_vars_dir.exists(): - shutil.rmtree(old_vars_dir) + if old_host_vars_dir.exists(): + shutil.rmtree(old_host_vars_dir) - shutil.copytree(temp_dir, old_vars_dir) # Copy new host vars dir - shutil.copy(temp_dir / "hosts.yaml", old_hosts_file) # Copy new hosts file + shutil.copytree(temp_dir, old_host_vars_dir) # Copy new host_vars dir + shutil.copy(temp_dir / "hosts.yaml", old_host_vars_dir) # Copy new hosts.yaml file shutil.rmtree(temp_dir) @@ -112,9 +112,8 @@ def generate_inventory_from_api() -> None: temp_dir = Path(tempfile.mkdtemp()) old_host_vars_dir = Path(settings.host_vars_dir) - old_hosts_file = Path(settings.hosts_file_dir) - with safe_write(temp_dir, old_host_vars_dir, old_hosts_file) as temp_dir: + with safe_write(temp_dir, old_host_vars_dir) as temp_dir: generate_host_vars_and_hosts_file(router_subscriptions, temp_dir) diff --git a/ansible_inventory_generator/config.py b/ansible_inventory_generator/config.py index 35e125bbb4ee077de6b67c84969c847accd404d8..8029c7a20563b3a03f56452cdd037dc75c3021aa 100644 --- a/ansible_inventory_generator/config.py +++ b/ansible_inventory_generator/config.py @@ -3,10 +3,9 @@ from pydantic.v1 import BaseSettings class Settings(BaseSettings): api_url: str - host_vars_dir: str - vars_file_name: str - hosts_file_dir: str gso_api_key: str + host_vars_dir: str + vars_file_name: str = "gso.yaml" class Config: env_file = "../.env" diff --git a/tests/test_inventory_generator.py b/tests/test_inventory_generator.py index 2b5fc13d7cf81cebbb60480724bff4b7af42e950..abe34f603c76cb200a4cb08032b047de808b8a40 100644 --- a/tests/test_inventory_generator.py +++ b/tests/test_inventory_generator.py @@ -55,7 +55,7 @@ def mocked_subscription_api_data(): "router_si_ipv4_network": "62.40.97.222/31", "router_ias_lt_ipv4_network": "83.97.89.116/31", "router_ias_lt_ipv6_network": "2001:798:1::2a4/126", - "router_vendor": "nokia", + "vendor": "nokia", "router_role": "p", "router_site": { "name": "SiteBlock", @@ -118,7 +118,7 @@ def mocked_subscription_api_data(): "router_si_ipv4_network": "62.40.97.222/31", "router_ias_lt_ipv4_network": "83.97.89.116/31", "router_ias_lt_ipv6_network": "2001:798:1::2a4/126", - "router_vendor": "juniper", + "vendor": "juniper", "router_role": "amt", "router_site": { "name": "SiteBlock", @@ -149,14 +149,14 @@ def mocked_subscription_api_data(): @pytest.fixture() def setup_test(tmp_dir, mocked_subscription_api_data): - with patch("ansible_inventory_generator.app.load_settings") as mock_load_settings, patch( - "requests.get" - ) as mock_get: + with ( + patch("ansible_inventory_generator.app.load_settings") as mock_load_settings, + patch("requests.get") as mock_get, + ): mock_load_settings.return_value = Settings( api_url="http://test", host_vars_dir=str(tmp_dir), vars_file_name="wfo_vars.yaml", - hosts_file_dir=str(tmp_dir), gso_api_key="random_gso_api_key", ) @@ -170,8 +170,8 @@ def setup_test(tmp_dir, mocked_subscription_api_data): def test_generate_inventory_from_api_valid_json(setup_test, tmp_dir, mocked_subscription_api_data): hosts_file = tmp_dir / "hosts.yaml" - amsterdam_host_vars = tmp_dir / "hostvars/amsterdam.nl.geant.net/wfo_vars.yaml" - utrecht_host_vars = tmp_dir / "hostvars/utrecht.nl.geant.net/wfo_vars.yaml" + amsterdam_host_vars = tmp_dir / "host_vars/amsterdam.nl.geant.net/wfo_vars.yaml" + utrecht_host_vars = tmp_dir / "host_vars/utrecht.nl.geant.net/wfo_vars.yaml" assert not amsterdam_host_vars.exists() assert not utrecht_host_vars.exists() @@ -218,8 +218,8 @@ def test_inventory_generation_handles_exceptions_and_preserves_file_integrity( ): paths = { "hosts": tmp_dir / "hosts.yaml", - "ams_vars": tmp_dir / "hostvars/amsterdam.nl.geant.net/wfo_vars.yaml", - "utr_vars": tmp_dir / "hostvars/utrecht.nl.geant.net/wfo_vars.yaml", + "ams_vars": tmp_dir / "host_vars/amsterdam.nl.geant.net/wfo_vars.yaml", + "utr_vars": tmp_dir / "host_vars/utrecht.nl.geant.net/wfo_vars.yaml", } file_contents = {