diff --git a/ansible_collections/arista/avd/plugins/action/verify_requirements.py b/ansible_collections/arista/avd/plugins/action/verify_requirements.py index f7677eccb4c..eeff92c80e6 100644 --- a/ansible_collections/arista/avd/plugins/action/verify_requirements.py +++ b/ansible_collections/arista/avd/plugins/action/verify_requirements.py @@ -345,17 +345,33 @@ def _get_running_collection_version(running_collection_name: str, result: dict) } -def check_running_from_source() -> None: - """Check if running from sources, if so recompile schemas and templates as needed.""" +def check_running_from_source() -> bool: + """ + Check if running from sources, if so recompile schemas and templates as needed. + + Returns: + -------- + bool: + True if schemas or templates were recompiled, False otherwise. + """ if not RUNNING_FROM_SOURCE: - return + return False # if running from source, path to pyavd and schema_tools has already been prepended to Python Path - from schema_tools.check_schemas import check_schemas - from schema_tools.compile_templates import check_templates + from schema_tools.check_schemas import check_schemas, rebuild_schemas + from schema_tools.compile_templates import check_templates, recompile_templates + + if schemas_recompiled := check_schemas(): + display.display("Schemas have changed, rebuilding...", color=C.COLOR_CHANGED) + rebuild_schemas() + display.display("Done.", color=C.COLOR_CHANGED) + + if templates_recompiled := check_templates(): + display.display("Templates have changed, recompiling...", color=C.COLOR_CHANGED) + recompile_templates() + display.display("Done.", color=C.COLOR_CHANGED) - check_schemas() - check_templates() + return schemas_recompiled or templates_recompiled class ActionModule(ActionBase): @@ -396,7 +412,8 @@ def run(self, tmp: Any = None, task_vars: dict | None = None) -> dict: _get_running_collection_version(running_collection_name, info["ansible"]) - check_running_from_source() + if check_running_from_source(): + result["changed"] = True display.display(f"AVD version {info['ansible']['collection']['version']}", color=C.COLOR_OK) if RUNNING_FROM_SOURCE: diff --git a/python-avd/schema_tools/check_schemas.py b/python-avd/schema_tools/check_schemas.py index aea43673d38..ce5dfc4f191 100644 --- a/python-avd/schema_tools/check_schemas.py +++ b/python-avd/schema_tools/check_schemas.py @@ -5,7 +5,7 @@ from pyavd.constants import RUNNING_FROM_SRC from schema_tools.build_schemas import build_schemas -from schema_tools.hash_dir import changed_hash +from schema_tools.hash_dir import changed_hash, hash_dir from .constants import ( EOS_CLI_CONFIG_GEN_FRAGMENTS_PATH, @@ -15,24 +15,30 @@ LOGGER = logging.getLogger(__name__) -def check_schemas() -> None: +def check_schemas() -> bool: """ Verify if eos_designs or eos_cli_config_gen schema need to be recompiled when running from source. - Always recompiling both + Returns: + -------- + bool: + True if any schema changed, False otherwise """ if not RUNNING_FROM_SRC: - return + return False LOGGER.info("pyavd running from source detected, checking schemas for any changes...") - # eos_designs - eos_designs_changed, eos_designs_new_hash = changed_hash(EOS_DESIGNS_FRAGMENTS_PATH) - eos_cli_config_gen_changed, eos_cli_config_gen_new_hash = changed_hash(EOS_CLI_CONFIG_GEN_FRAGMENTS_PATH) - if eos_designs_changed or eos_cli_config_gen_changed: - LOGGER.info("Recompiling schemas...") - build_schemas() - with (EOS_DESIGNS_FRAGMENTS_PATH / ".hash").open("w") as fd: - fd.write(eos_designs_new_hash) - with (EOS_CLI_CONFIG_GEN_FRAGMENTS_PATH / ".hash").open("w") as fd: - fd.write(eos_cli_config_gen_new_hash) + return changed_hash(EOS_DESIGNS_FRAGMENTS_PATH) or changed_hash(EOS_CLI_CONFIG_GEN_FRAGMENTS_PATH) + + +def rebuild_schemas() -> None: + """Rebuild the schema and saves the new hashes.""" + LOGGER.info("Recompiling schemas...") + build_schemas() + with (EOS_DESIGNS_FRAGMENTS_PATH / ".hash").open("w") as fd: + eos_designs_new_hash = hash_dir(EOS_DESIGNS_FRAGMENTS_PATH) + fd.write(eos_designs_new_hash) + with (EOS_CLI_CONFIG_GEN_FRAGMENTS_PATH / ".hash").open("w") as fd: + eos_cli_config_gen_new_hash = hash_dir(EOS_CLI_CONFIG_GEN_FRAGMENTS_PATH) + fd.write(eos_cli_config_gen_new_hash) diff --git a/python-avd/schema_tools/compile_templates.py b/python-avd/schema_tools/compile_templates.py index e76a429238b..cc45ecd4271 100644 --- a/python-avd/schema_tools/compile_templates.py +++ b/python-avd/schema_tools/compile_templates.py @@ -14,7 +14,7 @@ ) from pyavd.templater import Templar -from .hash_dir import changed_hash +from .hash_dir import changed_hash, hash_dir LOGGER = logging.getLogger(__name__) @@ -33,39 +33,77 @@ def compile_eos_designs_templates() -> None: templar.compile_templates_in_paths(precompiled_templates_path=EOS_DESIGNS_JINJA2_PRECOMPILED_TEMPLATE_PATH, searchpaths=[EOS_DESIGNS_JINJA2_TEMPLATE_PATH]) -def check_eos_designs_templates() -> None: - """Verify if eos_designs need to be recompiled when running from source.""" +def check_eos_designs_templates() -> bool: + """ + Verify if eos_designs need to be recompiled when running from source. + + Returns: + -------- + bool: + True if any templates changed, False otherwise + """ if not RUNNING_FROM_SRC: - return + return False LOGGER.info("pyavd running from source detected, checking eos_designs templates for any changes...") dir_path = EOS_DESIGNS_JINJA2_TEMPLATE_PATH - changed, new_hash = changed_hash(dir_path) - if changed: - LOGGER.info("Recompiling eos_designs templates...") - compile_eos_designs_templates() - with (dir_path / ".hash").open("w") as fd: - fd.write(new_hash) + return changed_hash(dir_path) + + +def recompile_eos_designs_templates() -> None: + """Recompile eos_designs templates.""" + LOGGER.info("Recompiling eos_designs templates...") + dir_path = EOS_DESIGNS_JINJA2_TEMPLATE_PATH + compile_eos_designs_templates() + new_hash = hash_dir(dir_path) + with (dir_path / ".hash").open("w") as fd: + fd.write(new_hash) + +def check_eos_cli_config_gen_templates() -> bool: + """ + Verify if eos_cli_config_gen need to be recompiled when running from source. -def check_eos_cli_config_gen_templates() -> None: - """Verify if eos_cli_config_gen need to be recompiled when running from source.""" + Returns: + -------- + bool: + True if any templates changed, False otherwise + """ if not RUNNING_FROM_SRC: - return + return False LOGGER.info("pyavd running from source detected, checking eos_cli_config_gen templates for any changes...") dir_path = EOS_CLI_CONFIG_GEN_JINJA2_TEMPLATE_PATH - changed, new_hash = changed_hash(dir_path) - if changed: - LOGGER.info("Recompiling eos_cli_config_gen templates...") - compile_eos_cli_config_gen_templates() - with (dir_path / ".hash").open("w") as fd: - fd.write(new_hash) + return changed_hash(dir_path) -def check_templates() -> None: - """Check both eos_designs and eos_cli_config_gen templates.""" - check_eos_cli_config_gen_templates() - check_eos_designs_templates() +def recompile_eos_cli_config_gen_templates() -> None: + """Recompile eos_cli_config_gen templates.""" + LOGGER.info("Recompiling eos_cli_config_gen templates...") + dir_path = EOS_CLI_CONFIG_GEN_JINJA2_TEMPLATE_PATH + compile_eos_cli_config_gen_templates() + new_hash = hash_dir(dir_path) + with (dir_path / ".hash").open("w") as fd: + fd.write(new_hash) + + +def check_templates() -> bool: + """ + Check both eos_designs and eos_cli_config_gen templates. + + Returns: + -------- + bool: + True if any templates changed, False otherwise + """ + eos_cli_config_gen_changed = check_eos_cli_config_gen_templates() + eos_designs_changed = check_eos_designs_templates() + return eos_designs_changed or eos_cli_config_gen_changed + + +def recompile_templates() -> None: + """Recompile eos_cli_config_gen and eos_designs templates.""" + recompile_eos_cli_config_gen_templates() + recompile_eos_designs_templates() diff --git a/python-avd/schema_tools/hash_dir.py b/python-avd/schema_tools/hash_dir.py index c73de8dbfaa..cc81cea1ceb 100644 --- a/python-avd/schema_tools/hash_dir.py +++ b/python-avd/schema_tools/hash_dir.py @@ -25,14 +25,16 @@ def _filehash(path: Path) -> str: return sha.hexdigest() -def changed_hash(path: Path) -> tuple[bool, str]: +def changed_hash(path: Path) -> bool: """ Check if the hash of the given path is different from the .hash file stored. If no .hash file is found, recompute - Returns (True, new_hash) if the hash has changed. - Returns (False, current_hash) if the hash has not changed. + Returns: + -------- + bool + True if the hash has changed else False """ saved_hash_path = path / ".hash" if saved_hash_path.exists(): @@ -41,7 +43,7 @@ def changed_hash(path: Path) -> tuple[bool, str]: else: saved_hash = "" current_hash = hash_dir(path) - return (True, current_hash) if saved_hash != current_hash else (False, current_hash) + return saved_hash != current_hash def hash_dir(path: Path) -> str: