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 __init__(self, **plugins):
|
||||||
def _lookup_priority(plugin):
|
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:
|
try:
|
||||||
return CONF.cloud_config_plugins.index(plugin)
|
return all_plugins.index(plugin)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# If the plugin was not specified in the order
|
# If plugin is not supported or does not exist
|
||||||
# list, then default to a sane and unreachable value.
|
# default to a sane and unreachable value.
|
||||||
return DEFAULT_ORDER_VALUE
|
return DEFAULT_ORDER_VALUE
|
||||||
|
|
||||||
self._expected_plugins = sorted(
|
self._expected_plugins = sorted(
|
||||||
|
@ -67,10 +70,17 @@ class CloudConfigPluginExecutor(object):
|
||||||
return cls(**content)
|
return cls(**content)
|
||||||
|
|
||||||
def execute(self):
|
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
|
reboot = execcmd.NO_REBOOT
|
||||||
plugins = factory.load_plugins()
|
plugins = factory.load_plugins()
|
||||||
for plugin_name, value in self._expected_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)
|
method = plugins.get(plugin_name)
|
||||||
if not method:
|
if not method:
|
||||||
LOG.error("Plugin %r is currently not supported", plugin_name)
|
LOG.error("Plugin %r is currently not supported", plugin_name)
|
||||||
|
|
|
@ -51,6 +51,23 @@ class CloudConfigPluginTests(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
CONF.cloud_config_plugins = orig
|
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):
|
def test_executor_from_yaml(self):
|
||||||
for invalid in (mock.sentinel.yaml, None, 1, int, '{}'):
|
for invalid in (mock.sentinel.yaml, None, 1, int, '{}'):
|
||||||
with self.assertRaises(cloudconfig.CloudConfigError):
|
with self.assertRaises(cloudconfig.CloudConfigError):
|
||||||
|
|
|
@ -247,8 +247,9 @@ The following cloud-config directives are supported:
|
||||||
- ['echo', '1']
|
- ['echo', '1']
|
||||||
|
|
||||||
|
|
||||||
The cloud-config directives are executed in the following order: write_files, set_timezone,
|
The cloud-config directives are executed by default in the following order: write_files,
|
||||||
set_hostname, ntp, runcmd.
|
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
|
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
|
is performed at the end of the cloud-config execution (after all the directives have been
|
||||||
|
|
Loading…
Reference in New Issue