diff --git a/changelog/61946.fixed b/changelog/61946.fixed new file mode 100644 index 000000000000..2ff01bcf48bb --- /dev/null +++ b/changelog/61946.fixed @@ -0,0 +1 @@ +Fix salt-cloud sync_after_install functionality diff --git a/doc/topics/cloud/misc.rst b/doc/topics/cloud/misc.rst index 80665cf25298..881553498050 100644 --- a/doc/topics/cloud/misc.rst +++ b/doc/topics/cloud/misc.rst @@ -44,13 +44,13 @@ be configured to use SCP instead. Sync After Install ================== -Salt allows users to create custom modules, grains, and states which can be -synchronised to minions to extend Salt with further functionality. +Salt allows users to create custom plugins such as execution, grains, and state +modules which can be synchronised to minions to extend Salt with further +functionality. -This option will inform Salt Cloud to synchronise your custom modules, grains, -states or all these to the minion just after it has been created. For this to -happen, the following line needs to be added to the main cloud -configuration file: +This option will inform Salt Cloud to synchronise your custom modules to the +minion just after it has been created. For this to happen, the following line +needs to be added to the main cloud configuration file: .. code-block:: yaml @@ -60,10 +60,29 @@ The available options for this setting are: .. code-block:: yaml - modules + all + beacons + clouds + engines + executors grains + log + matchers + modules + output + pillar + proxymodules + renderers + returners + sdb + serializers states - all + thorium + utils + +A present and non-falsy value that doesn't match one of these list items will +assume `all`, so `sync_after_install: True` and `sync_after_install: all` are +equivalent (though the former will produce a warning). Setting Up New Salt Masters diff --git a/salt/cloud/__init__.py b/salt/cloud/__init__.py index b17c6bf03e51..eac1447079a0 100644 --- a/salt/cloud/__init__.py +++ b/salt/cloud/__init__.py @@ -1225,14 +1225,33 @@ def create(self, vm_, local_master=True): ): output = self.clouds[func](vm_) if output is not False and "sync_after_install" in self.opts: - if self.opts["sync_after_install"] not in ( + if self.opts["sync_after_install"] and self.opts[ + "sync_after_install" + ] not in ( "all", + "beacons", + "clouds", + "engines", + "executors", + "grains", + "log", + "matchers", "modules", + "output", + "pillar", + "proxymodules", + "renderers", + "returners", + "sdb", + "serializers", "states", - "grains", + "thorium", + "utils", ): - log.error("Bad option for sync_after_install") - return output + log.warning( + "Bad option for sync_after_install. Defaulting to 'all'" + ) + self.opts["sync_after_install"] = "all" # A small pause helps the sync work more reliably time.sleep(3) @@ -1240,7 +1259,7 @@ def create(self, vm_, local_master=True): start = int(time.time()) while int(time.time()) < start + 60: # We'll try every seconds, up to a minute - mopts_ = salt.config.DEFAULT_MASTER_OPTS + mopts_ = copy.deepcopy(salt.config.DEFAULT_MASTER_OPTS) conf_path = "/".join(self.opts["conf_file"].split("/")[:-1]) mopts_.update( salt.config.master_config(os.path.join(conf_path, "master")) diff --git a/tests/pytests/unit/cloud/test_cloud.py b/tests/pytests/unit/cloud/test_cloud.py new file mode 100644 index 000000000000..1d3952efec20 --- /dev/null +++ b/tests/pytests/unit/cloud/test_cloud.py @@ -0,0 +1,38 @@ +import copy + +import pytest +import salt.config +from salt.cloud import Cloud +from tests.support.mock import MagicMock, patch + + +@pytest.fixture +def master_config(): + opts = copy.deepcopy(salt.config.DEFAULT_MASTER_OPTS) + opts["parallel"] = False + opts["providers"] = { + "test": {}, + } + return opts + + +@pytest.fixture +def vm_config(): + return { + "driver": "test", + "name": "test", + "provider": "test:test", + } + + +def test_cloud_create_attempt_sync_after_install(master_config, vm_config): + master_config["sync_after_install"] = "all" + cloud = Cloud(master_config) + cloud.clouds["test.create"] = lambda x: True + + with patch( + "salt.client.get_local_client", + MagicMock(return_value=MagicMock(return_value=True)), + ): + ret = cloud.create(vm_config) + assert ret