summaryrefslogtreecommitdiff
path: root/cloudinit
diff options
context:
space:
mode:
authorDaniel Watkins <daniel.watkins@canonical.com>2019-03-14 23:06:47 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2019-03-14 23:06:47 +0000
commitf2fd6eac4407e60d0e98826ab03847dda4cde138 (patch)
treecbd47c6633145a5de7e90768252623c149605fb1 /cloudinit
parent3acaacc92be1b7d7bad099c323d6e923664a8afa (diff)
downloadvyos-cloud-init-f2fd6eac4407e60d0e98826ab03847dda4cde138.tar.gz
vyos-cloud-init-f2fd6eac4407e60d0e98826ab03847dda4cde138.zip
DataSource: move update_events from a class to an instance attribute
Currently, DataSourceAzure updates self.update_events in __init__. As update_events is a class attribute on DataSource, this updates it for all instances of classes derived from DataSource including those for other clouds. This means that if DataSourceAzure is even instantiated, its behaviour is applied to whichever data source ends up being used for boot. To address this, update_events is moved from a class attribute to an instance attribute (that is therefore populated at instantiation time). This retains the defaults for all DataSource sub-class instances, but avoids them being able to mutate the state in instances of other DataSource sub-classes. update_events is only ever referenced on an instance of DataSource (or a sub-class); no code relies on it being a class attribute. (In fact, it's only used within methods on DataSource or its sub-classes, so it doesn't even _need_ to remain public, though I think it's appropriate for it to be public.) DataSourceScaleway is also updated to move update_events from a class attribute to an instance attribute, as the class attribute would now be masked by the DataSource instance attribute. LP: #1819913
Diffstat (limited to 'cloudinit')
-rw-r--r--cloudinit/sources/DataSourceScaleway.py3
-rw-r--r--cloudinit/sources/__init__.py6
-rw-r--r--cloudinit/sources/tests/test_init.py15
3 files changed, 20 insertions, 4 deletions
diff --git a/cloudinit/sources/DataSourceScaleway.py b/cloudinit/sources/DataSourceScaleway.py
index b573b382..54bfc1fe 100644
--- a/cloudinit/sources/DataSourceScaleway.py
+++ b/cloudinit/sources/DataSourceScaleway.py
@@ -171,10 +171,11 @@ def query_data_api(api_type, api_address, retries, timeout):
class DataSourceScaleway(sources.DataSource):
dsname = "Scaleway"
- update_events = {'network': [EventType.BOOT_NEW_INSTANCE, EventType.BOOT]}
def __init__(self, sys_cfg, distro, paths):
super(DataSourceScaleway, self).__init__(sys_cfg, distro, paths)
+ self.update_events = {
+ 'network': {EventType.BOOT_NEW_INSTANCE, EventType.BOOT}}
self.ds_cfg = util.mergemanydict([
util.get_cfg_by_path(sys_cfg, ["datasource", "Scaleway"], {}),
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index e6966b31..1604932d 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -164,9 +164,6 @@ class DataSource(object):
# A datasource which supports writing network config on each system boot
# would call update_events['network'].add(EventType.BOOT).
- # Default: generate network config on new instance id (first boot).
- update_events = {'network': set([EventType.BOOT_NEW_INSTANCE])}
-
# N-tuple listing default values for any metadata-related class
# attributes cached on an instance by a process_data runs. These attribute
# values are reset via clear_cached_attrs during any update_metadata call.
@@ -191,6 +188,9 @@ class DataSource(object):
self.vendordata = None
self.vendordata_raw = None
+ # Default: generate network config on new instance id (first boot).
+ self.update_events = {'network': {EventType.BOOT_NEW_INSTANCE}}
+
self.ds_cfg = util.get_cfg_by_path(
self.sys_cfg, ("datasource", self.dsname), {})
if not self.ds_cfg:
diff --git a/cloudinit/sources/tests/test_init.py b/cloudinit/sources/tests/test_init.py
index 6378e98b..cb1912be 100644
--- a/cloudinit/sources/tests/test_init.py
+++ b/cloudinit/sources/tests/test_init.py
@@ -575,6 +575,21 @@ class TestDataSource(CiTestCase):
" events: New instance first boot",
self.logs.getvalue())
+ def test_data_sources_cant_mutate_update_events_for_others(self):
+ """update_events shouldn't be changed for other DSes (LP: #1819913)"""
+
+ class ModifyingDS(DataSource):
+
+ def __init__(self, sys_cfg, distro, paths):
+ # This mirrors what DataSourceAzure does which causes LP:
+ # #1819913
+ DataSource.__init__(self, sys_cfg, distro, paths)
+ self.update_events['network'].add(EventType.BOOT)
+
+ before_update_events = copy.deepcopy(self.datasource.update_events)
+ ModifyingDS(self.sys_cfg, self.distro, self.paths)
+ self.assertEqual(before_update_events, self.datasource.update_events)
+
class TestRedactSensitiveData(CiTestCase):