Conrad Hoffmann has proposed merging ~bitfehler/cloud-init:bitfehler/load_seed into cloud-init:master.
Requested reviews: cloud-init commiters (cloud-init-dev) For more details, see: https://code.launchpad.net/~bitfehler/cloud-init/+git/cloud-init/+merge/369814 -- Your team cloud-init commiters is requested to review the proposed merge of ~bitfehler/cloud-init:bitfehler/load_seed into cloud-init:master.
diff --git a/cloudinit/sources/DataSourceCloudStack.py b/cloudinit/sources/DataSourceCloudStack.py index f185dc7..3605076 100644 --- a/cloudinit/sources/DataSourceCloudStack.py +++ b/cloudinit/sources/DataSourceCloudStack.py @@ -110,12 +110,15 @@ class DataSourceCloudStack(sources.DataSource): return self.cfg def _get_data(self): - seed_ret = {} - if util.read_optional_seed(seed_ret, base=(self.seed_dir + "/")): - self.userdata_raw = seed_ret['user-data'] - self.metadata = seed_ret['meta-data'] + try: + # Using `required` wrapped in try because we want both or none + seed = util.load_seed(self.seed_dir, ['meta-data', 'user-data']) + self.userdata_raw = seed['user-data'] + self.metadata = seed['meta-data'] LOG.debug("Using seeded cloudstack data from: %s", self.seed_dir) return True + except Exception: + pass try: if not self.wait_for_metadata_service(): return False diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py index 8a9e5dd..da92875 100644 --- a/cloudinit/sources/DataSourceNoCloud.py +++ b/cloudinit/sources/DataSourceNoCloud.py @@ -165,13 +165,11 @@ class DataSourceNoCloud(sources.DataSource): # This could throw errors, but the user told us to do it # so if errors are raised, let them raise - (md_seed, ud) = util.read_seeded(seedfrom, timeout=None) + seed = util.load_seed(seedfrom, timeout=None, **pp2d_kwargs) LOG.debug("Using seeded cache data from %s", seedfrom) # Values in the command line override those from the seed - mydata['meta-data'] = util.mergemanydict([mydata['meta-data'], - md_seed]) - mydata['user-data'] = ud + mydata = _merge_new_seed(mydata, seed) found.append(seedfrom) # Now that we have exhausted any other places merge in the defaults @@ -357,8 +355,10 @@ def _merge_new_seed(cur, seeded): ret['meta-data'] = util.mergemanydict([cur['meta-data'], newmd]) if seeded.get('network-config'): - ret['network-config'] = _maybe_remove_top_network( - util.load_yaml(seeded.get('network-config'))) + newnc = seeded['network-config'] + if not isinstance(newnc, dict): + newnc = util.load_yaml(seeded['network-config']) + ret['network-config'] = _maybe_remove_top_network(newnc) if 'user-data' in seeded: ret['user-data'] = seeded['user-data'] diff --git a/cloudinit/sources/DataSourceOVF.py b/cloudinit/sources/DataSourceOVF.py index 70e7a5c..dd9b994 100644 --- a/cloudinit/sources/DataSourceOVF.py +++ b/cloudinit/sources/DataSourceOVF.py @@ -262,10 +262,10 @@ class DataSourceOVF(sources.DataSource): seedfrom, self) return False - (md_seed, ud) = util.read_seeded(seedfrom, timeout=None) + seed = util.load_seed(seedfrom, ['meta-data'], timeout=None) LOG.debug("Using seeded cache data from %s", seedfrom) - md = util.mergemanydict([md, md_seed]) + md = util.mergemanydict([md, seed.get('meta-data', {})]) found.append(seedfrom) # Now that we have exhausted any other places merge in the defaults diff --git a/cloudinit/util.py b/cloudinit/util.py index aa23b3f..43bb0e8 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -892,22 +892,6 @@ def runparts(dirp, skip_no_exist=True, exe_prefix=None): % (len(failed), len(attempted))) -# read_optional_seed -# returns boolean indicating success or failure (presense of files) -# if files are present, populates 'fill' dictionary with 'user-data' and -# 'meta-data' entries -def read_optional_seed(fill, base="", ext="", timeout=5): - try: - (md, ud) = read_seeded(base, ext, timeout) - fill['user-data'] = ud - fill['meta-data'] = md - return True - except url_helper.UrlError as e: - if e.code == url_helper.NOT_FOUND: - return False - raise - - def fetch_ssl_details(paths=None): ssl_details = {} # Lookup in these locations for ssl key/cert files @@ -974,34 +958,31 @@ def load_yaml(blob, default=None, allowed=(dict,)): return loaded -def read_seeded(base="", ext="", timeout=5, retries=10, file_retries=0): +def load_seed(base='', required=None, optional=None, timeout=5): + result = {} + if required is None: + required = [] + if optional is None: + optional = [] if base.startswith("/"): base = "file://%s" % base - # default retries for file is 0. for network is 10 - if base.startswith("file://"): - retries = file_retries + for item in required + optional: + try: + url = url_helper.combine_url(base, item) + resp = url_helper.read_file_or_url(url, timeout) + if resp.ok(): + if item in ['meta-data', 'network-config']: + result[item] = load_yaml(decode_binary(resp.contents)) + else: + result[item] = resp.contents + except url_helper.UrlError as e: + if item in optional and e.code == url_helper.NOT_FOUND: + pass + else: + raise e - if base.find("%s") >= 0: - ud_url = base % ("user-data" + ext) - md_url = base % ("meta-data" + ext) - else: - ud_url = "%s%s%s" % (base, "user-data", ext) - md_url = "%s%s%s" % (base, "meta-data", ext) - - md_resp = url_helper.read_file_or_url(md_url, timeout, retries, - file_retries) - md = None - if md_resp.ok(): - md = load_yaml(decode_binary(md_resp.contents), default={}) - - ud_resp = url_helper.read_file_or_url(ud_url, timeout, retries, - file_retries) - ud = None - if ud_resp.ok(): - ud = ud_resp.contents - - return (md, ud) + return result def read_conf_d(confd): diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index 0e71db8..a31031a 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -724,21 +724,52 @@ class TestMessageFromString(helpers.TestCase): self.assertNotIn('\x00', roundtripped) -class TestReadSeeded(helpers.TestCase): +class TestLoadSeed(helpers.TestCase): def setUp(self): - super(TestReadSeeded, self).setUp() + super(TestLoadSeed, self).setUp() self.tmp = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, self.tmp) - def test_unicode_not_messed_up(self): + def test_simple_seed(self): ud = b"userdatablob" helpers.populate_dir( self.tmp, {'meta-data': "key1: val1", 'user-data': ud}) - sdir = self.tmp + os.path.sep - (found_md, found_ud) = util.read_seeded(sdir) + seed = util.load_seed(self.tmp, required=['meta-data', 'user-data']) + found_md = seed.get('meta-data', {}) + found_ud = seed.get('user-data', '') + + self.assertEqual(found_md, {'key1': 'val1'}) + self.assertEqual(found_ud, ud) + + def test_ignores_optional(self): + ud = b"userdatablob" + helpers.populate_dir( + self.tmp, {'meta-data': 'key1: val1', 'user-data': ud}) + seed = util.load_seed( + self.tmp, ['meta-data', 'user-data'], ['network-config']) + found_md = seed.get('meta-data', {}) + found_ud = seed.get('user-data', '') + + self.assertEqual(found_md, {'key1': 'val1'}) + self.assertEqual(found_ud, ud) + + def test_loads_optional(self): + ud = b"userdatablob" + helpers.populate_dir( + self.tmp, { + 'meta-data': 'key1: val1', + 'user-data': ud, + 'network-config': 'key: val' + }) + seed = util.load_seed( + self.tmp, ['meta-data', 'user-data'], ['network-config']) + found_md = seed.get('meta-data', {}) + found_ud = seed.get('user-data', '') + found_nc = seed.get('network-config', {}) self.assertEqual(found_md, {'key1': 'val1'}) self.assertEqual(found_ud, ud) + self.assertEqual(found_nc, {'key': 'val'}) class TestSubp(helpers.CiTestCase):
_______________________________________________ Mailing list: https://launchpad.net/~cloud-init-dev Post to : cloud-init-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~cloud-init-dev More help : https://help.launchpad.net/ListHelp