diff --git a/kubemarine/core/flow.py b/kubemarine/core/flow.py index beadc28b5..57634298d 100755 --- a/kubemarine/core/flow.py +++ b/kubemarine/core/flow.py @@ -232,6 +232,7 @@ def create_empty_context(args: dict, procedure: str) -> dict: "execution_arguments": deepcopy(args), 'initial_procedure': procedure, 'preserve_inventory': True, + 'make_finalized_inventory': True, 'load_inventory_silent': False, 'runtime_vars': {}, 'result': ['summary_report'], diff --git a/kubemarine/core/resources.py b/kubemarine/core/resources.py index 963881a95..646b30391 100644 --- a/kubemarine/core/resources.py +++ b/kubemarine/core/resources.py @@ -284,14 +284,14 @@ def reset_cluster(self, stage: c.EnrichmentStage) -> None: def dump_finalized_inventory(self, cluster: c.KubernetesCluster) -> None: finalized_filename = "cluster_finalized.yaml" - if not self._make_finalized_inventory(finalized_filename): + if not self.context['make_finalized_inventory']: return - finalized_inventory = cluster.make_finalized_inventory(self.finalization_functions()) + finalized_inventory = self.make_finalized_inventory(cluster) self._store_finalized_inventory(finalized_inventory, finalized_filename) - def _make_finalized_inventory(self, finalized_filename: str) -> bool: - return utils.is_dump_allowed(self.context, finalized_filename) + def make_finalized_inventory(self, cluster: c.KubernetesCluster) -> dict: + return cluster.make_finalized_inventory(self.finalization_functions()) def _store_finalized_inventory(self, finalized_inventory: dict, finalized_filename: str) -> None: data = yaml.dump(finalized_inventory) diff --git a/kubemarine/demo.py b/kubemarine/demo.py index a13cbc3b2..be5dccf24 100644 --- a/kubemarine/demo.py +++ b/kubemarine/demo.py @@ -201,7 +201,7 @@ def upload_info_new_control_planes(self) -> None: class FakeKubernetesCluster(KubernetesCluster): def __init__(self, *args: Any, **kwargs: Any): - self.resources: FakeResources = kwargs.pop("resources") + self.resources: FakeClusterResources = kwargs.pop("resources") self.fake_shell = self.resources.fake_shell self.fake_fs = self.resources.fake_fs self.uploaded_archives: List[str] = [] @@ -217,20 +217,16 @@ def make_group(self, ips: Iterable[_AnyConnectionTypes]) -> FakeNodeGroup: return FakeNodeGroup(ips, self) -class FakeResources(DynamicResources): - def __init__(self, context: dict, inventory: dict = None, procedure_inventory: dict = None, +class FakeClusterResources(DynamicResources): + def __init__(self, context: dict, + *, nodes_context: Dict[str, Any] = None, - fake_shell: FakeShell = None, fake_fs: FakeFS = None, make_finalized_inventory: Optional[bool] = False): + fake_shell: FakeShell = None, fake_fs: FakeFS = None): super().__init__(context) - self.inventory_filepath = None - self.procedure_inventory_filepath = None self.fake_shell = fake_shell if fake_shell else FakeShell() self.fake_fs = fake_fs if fake_fs else FakeFS() - self._inventory = inventory - self._procedure_inventory = procedure_inventory self.finalized_inventory: dict = {} - self.make_finalized_inventory = make_finalized_inventory self._enrichment_functions = super().enrichment_functions() # Let's do not assign self._nodes_context directly to make it more close to the real enrichment. @@ -247,18 +243,13 @@ def working_inventory(self) -> dict: return {} - def _store_inventory(self, inventory: dict) -> None: - pass - - def _make_finalized_inventory(self, finalized_filename: str) -> bool: - if self.make_finalized_inventory is None: - return super()._make_finalized_inventory(finalized_filename) - - return self.make_finalized_inventory - def _store_finalized_inventory(self, finalized_inventory: dict, finalized_filename: str) -> None: self.finalized_inventory = finalized_inventory - utils.dump_file(self, yaml.dump(finalized_inventory), finalized_filename) + super()._store_finalized_inventory(finalized_inventory, finalized_filename) + + def cluster_if_initialized(self) -> Optional[FakeKubernetesCluster]: + cluster = super().cluster_if_initialized() + return None if cluster is None else cast(FakeKubernetesCluster, cluster) def cluster(self, stage: EnrichmentStage = EnrichmentStage.PROCEDURE) -> FakeKubernetesCluster: return cast(FakeKubernetesCluster, super().cluster(stage)) @@ -290,6 +281,26 @@ def enrichment_functions(self) -> List[EnrichmentFunction]: return self._enrichment_functions +class FakeResources(FakeClusterResources): + def __init__(self, context: dict, inventory: dict = None, + *, + procedure_inventory: dict = None, + nodes_context: Dict[str, Any] = None, + fake_shell: FakeShell = None, fake_fs: FakeFS = None): + super().__init__(context, nodes_context=nodes_context, fake_shell=fake_shell, fake_fs=fake_fs) + self.inventory_filepath = None + self.procedure_inventory_filepath = None + self._inventory = inventory + self._procedure_inventory = procedure_inventory + + def _store_inventory(self, inventory: dict) -> None: + pass + + def _store_finalized_inventory(self, finalized_inventory: dict, finalized_filename: str) -> None: + self.finalized_inventory = finalized_inventory + utils.dump_file(self, yaml.dump(finalized_inventory), finalized_filename) + + class FakeConnection(fabric.connection.Connection): # type: ignore[misc] def __init__(self, ip: str, fake_shell: FakeShell, fake_fs: FakeFS, **kw: Any): @@ -462,6 +473,7 @@ def create_silent_context(args: list = None, procedure: str = 'install') -> dict context: dict = procedures.import_procedure(procedure).create_context(args) context['preserve_inventory'] = False + context['make_finalized_inventory'] = False context['load_inventory_silent'] = True parsed_args: dict = context['execution_arguments'] diff --git a/kubemarine/procedures/do.py b/kubemarine/procedures/do.py index 057eaa26a..1da41c3bf 100755 --- a/kubemarine/procedures/do.py +++ b/kubemarine/procedures/do.py @@ -97,6 +97,7 @@ def create_context(cli_arguments: List[str] = None) -> dict: 'config': configfile_path, }, procedure='do') context['preserve_inventory'] = False + context['make_finalized_inventory'] = False context['load_inventory_silent'] = True context['do_arguments'] = arguments diff --git a/test/unit/core/test_run_actions.py b/test/unit/core/test_run_actions.py index bc04cbea3..36f97a38d 100644 --- a/test/unit/core/test_run_actions.py +++ b/test/unit/core/test_run_actions.py @@ -112,7 +112,7 @@ def _new_resources(self) -> demo.FakeResources: return FakeResources(self.context, nodes_context=demo.generate_nodes_context(self.inventory)) def _run_actions(self, actions: List[action.Action], - resources: FakeResources = None, + resources: res.DynamicResources = None, exception_message: str = None) -> List[str]: if resources is None: resources = self._new_resources() @@ -194,6 +194,18 @@ def test_install_action_disable_dump(self): actual_dump_content = self._list_dump_content() self.assertEqual(expected_dump_content, actual_dump_content) + def test_cluster_finalized_disable_dump_without_act(self): + self.prepare_context(['--disable-dump', '--without-act'], procedure='install') + + with test_utils.chdir(self.tmpdir.name): + resources = test_utils.PackageStubResources( + self.context, nodes_context=demo.generate_nodes_context(self.inventory)) + + self._run_actions([self._prepare_action(install.InstallAction())], + resources=resources) + + self.assertTrue(os.path.exists(os.path.join(self.tmpdir.name, 'cluster_finalized.yaml'))) + def test_install_action_failed_task(self): self.prepare_context(procedure='install') @@ -489,7 +501,7 @@ def cluster_action(resources_: res.DynamicResources): raise Exception("test") resources = self._new_resources() - resources.make_finalized_inventory = False + resources.context['make_finalized_inventory'] = False uploaded_archives = self._run_actions([ test_utils.new_action("test_inventory1", action=inventory_action, recreate_inventory=recreate_inventory), test_utils.new_action("test_cluster1", action=cluster_action), diff --git a/test/unit/test_do.py b/test/unit/test_do.py index a12390df5..e42c08ab0 100644 --- a/test/unit/test_do.py +++ b/test/unit/test_do.py @@ -28,8 +28,6 @@ def test_command_run_any_node(self): hosts = [node['address'] for node in inventory['nodes']] context = do.create_context(['--', 'whoami']) resources = demo.new_resources(inventory, context=context) - # Set make_finalized_inventory=None to invoke real method making it closer to the real work - resources.make_finalized_inventory = None results = demo.create_hosts_result(hosts, stdout='root\n', hide=False) resources.fake_shell.add(results, 'sudo', ['whoami']) diff --git a/test/unit/utils.py b/test/unit/utils.py index f98e8eb0d..acc040b4a 100644 --- a/test/unit/utils.py +++ b/test/unit/utils.py @@ -13,6 +13,7 @@ # limitations under the License. import inspect import logging +import os import re import unittest from contextlib import contextmanager @@ -29,18 +30,25 @@ from kubemarine.procedures import migrate_kubemarine -class FakeResources(demo.FakeResources): - def __init__(self, *args: Any, **kwargs: Any): - kwargs['make_finalized_inventory'] = True - super().__init__(*args, **kwargs) +class PackageStubResources(demo.FakeClusterResources): + def __init__(self, context: dict, + *, + nodes_context: Dict[str, Any] = None, + fake_shell: demo.FakeShell = None, fake_fs: demo.FakeFS = None): + super().__init__(context, nodes_context=nodes_context, fake_shell=fake_shell, fake_fs=fake_fs) + context['make_finalized_inventory'] = True def collect_action_result(self) -> None: super().collect_action_result() cluster = self.cluster_if_initialized() - if isinstance(cluster, demo.FakeKubernetesCluster): + if cluster is not None: stub_associations_packages(cluster, {}) +class FakeResources(demo.FakeResources, PackageStubResources): + pass + + def make_finalized_inventory(cluster: demo.FakeKubernetesCluster, *, stub_cache_packages: bool = True) -> dict: @@ -48,9 +56,7 @@ def make_finalized_inventory(cluster: demo.FakeKubernetesCluster, stub_associations_packages(cluster, {}) resources = cluster.resources - resources.make_finalized_inventory = True - resources.dump_finalized_inventory(cluster) - return resources.finalized_inventory + return resources.make_finalized_inventory(cluster) def stub_detect_packages(cluster: demo.FakeKubernetesCluster, packages_hosts_stub: Dict[str, Dict[str, str]]): @@ -171,6 +177,16 @@ def mocked(filename: str = None, ext: str = None) -> str: yield +@contextmanager +def chdir(dir_: str) -> Iterator[None]: + orig_cwd = os.getcwd() + os.chdir(dir_) + try: + yield + finally: + os.chdir(orig_cwd) + + def new_action(id_: str, *, action: Callable[[res.DynamicResources], Any] = None, recreate_inventory: bool = False) -> Action: