Fix Py27 cloud-config ordering
On Py27, the yaml module implementation uses a normal dictionary for implementation, resulting in arbitrary order for the parsed yaml. If the config option cloud_config_plugins is not set or empty, fallback to the default order defined in the factory. Config option `cloud_config_plugins` is now used for filtering the cloud config plugins to be executed, which was the original intended behaviour. Change-Id: I59ea56e473ab343a826ff8c38787cb7f11cebd27
This commit is contained in:
parent
a77477e16e
commit
75c6a0e0f8
@ -42,11 +42,14 @@ class CloudConfigPluginExecutor(object):
|
||||
|
||||
def __init__(self, **plugins):
|
||||
def _lookup_priority(plugin):
|
||||
all_plugins = (CONF.cloud_config_plugins or
|
||||
list(factory.PLUGINS.keys()))
|
||||
# return the order from the config or default list
|
||||
try:
|
||||
return CONF.cloud_config_plugins.index(plugin)
|
||||
return all_plugins.index(plugin)
|
||||
except ValueError:
|
||||
# If the plugin was not specified in the order
|
||||
# list, then default to a sane and unreachable value.
|
||||
# If plugin is not supported or does not exist
|
||||
# default to a sane and unreachable value.
|
||||
return DEFAULT_ORDER_VALUE
|
||||
|
||||
self._expected_plugins = sorted(
|
||||
@ -67,10 +70,17 @@ class CloudConfigPluginExecutor(object):
|
||||
return cls(**content)
|
||||
|
||||
def execute(self):
|
||||
"""Call each plugin, in the order requested by the user."""
|
||||
"""Call each plugin, in the order defined by _lookup_priority"""
|
||||
reboot = execcmd.NO_REBOOT
|
||||
plugins = factory.load_plugins()
|
||||
for plugin_name, value in self._expected_plugins:
|
||||
if CONF.cloud_config_plugins:
|
||||
try:
|
||||
CONF.cloud_config_plugins.index(plugin_name)
|
||||
except ValueError:
|
||||
LOG.info("Plugin %r is disabled", plugin_name)
|
||||
continue
|
||||
|
||||
method = plugins.get(plugin_name)
|
||||
if not method:
|
||||
LOG.error("Plugin %r is currently not supported", plugin_name)
|
||||
|
@ -51,6 +51,23 @@ class CloudConfigPluginTests(unittest.TestCase):
|
||||
finally:
|
||||
CONF.cloud_config_plugins = orig
|
||||
|
||||
def test_default_priority(self):
|
||||
expected = [
|
||||
('write_files', 0),
|
||||
('hostname', 3),
|
||||
('runcmd', 1),
|
||||
('invalid1', 1),
|
||||
('invalid2', 2),
|
||||
]
|
||||
|
||||
executor = cloudconfig.CloudConfigPluginExecutor(
|
||||
runcmd=1,
|
||||
invalid1=1,
|
||||
hostname=3,
|
||||
invalid2=2,
|
||||
write_files=0)
|
||||
self.assertEqual(expected, executor._expected_plugins)
|
||||
|
||||
def test_executor_from_yaml(self):
|
||||
for invalid in (mock.sentinel.yaml, None, 1, int, '{}'):
|
||||
with self.assertRaises(cloudconfig.CloudConfigError):
|
||||
|
@ -247,8 +247,9 @@ The following cloud-config directives are supported:
|
||||
- ['echo', '1']
|
||||
|
||||
|
||||
The cloud-config directives are executed in the following order: write_files, set_timezone,
|
||||
set_hostname, ntp, runcmd.
|
||||
The cloud-config directives are executed by default in the following order: write_files,
|
||||
set_timezone, set_hostname, ntp, groups, users, runcmd. Use config option `cloud_config_plugins`
|
||||
to filter or to change the order of the cloud config plugins.
|
||||
|
||||
The execution of set_hostname or runcmd can request a reboot if needed. The reboot
|
||||
is performed at the end of the cloud-config execution (after all the directives have been
|
||||
|
Loading…
x
Reference in New Issue
Block a user