From b7632baa817a8425c2dcab4a01e2f7f0983e5f9e Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Fri, 19 Dec 2014 11:28:35 -0500 Subject: add user-data encoding support for gce --- cloudinit/sources/DataSourceGCE.py | 9 +++++ tests/unittests/test_datasource/test_gce.py | 59 +++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/cloudinit/sources/DataSourceGCE.py b/cloudinit/sources/DataSourceGCE.py index 7091e3c1..e6f3651c 100644 --- a/cloudinit/sources/DataSourceGCE.py +++ b/cloudinit/sources/DataSourceGCE.py @@ -15,6 +15,8 @@ # along with this program. If not, see . +from base64 import b64decode + from cloudinit import log as logging from cloudinit import util from cloudinit import sources @@ -58,6 +60,7 @@ class DataSourceGCE(sources.DataSource): ('local-hostname', 'instance/hostname', True), ('public-keys', 'project/attributes/sshKeys', False), ('user-data', 'instance/attributes/user-data', False), + ('user-data-encoding', 'instance/attributes/user-data-encoding', False), ] # if we cannot resolve the metadata server, then no point in trying @@ -101,6 +104,12 @@ class DataSourceGCE(sources.DataSource): lines = self.metadata['public-keys'].splitlines() self.metadata['public-keys'] = [self._trim_key(k) for k in lines] + if self.metadata.get('user-data-encoding'): + if self.metadata['user-data-encoding'] == 'base64': + self.metadata['user-data'] = b64decode(self.metadata['user-data']) + else: + LOG.warn('user-data-encoding: unknown encoding specified', None, None) + return found @property diff --git a/tests/unittests/test_datasource/test_gce.py b/tests/unittests/test_datasource/test_gce.py index 60a0ce48..957747ef 100644 --- a/tests/unittests/test_datasource/test_gce.py +++ b/tests/unittests/test_datasource/test_gce.py @@ -18,6 +18,7 @@ import httpretty import re +from base64 import b64encode, b64decode from urlparse import urlparse from cloudinit import settings @@ -30,29 +31,45 @@ GCE_META = { 'instance/id': '123', 'instance/zone': 'foo/bar', 'project/attributes/sshKeys': 'user:ssh-rsa AA2..+aRD0fyVw== root@server', - 'instance/hostname': 'server.project-name.local', + 'instance/hostname': 'server.project-foo.local', 'instance/attributes/user-data': '/bin/echo foo\n', + 'instance/attributes/user-data-encoding':'', } GCE_META_PARTIAL = { - 'instance/id': '123', - 'instance/hostname': 'server.project-name.local', + 'instance/id': '1234', + 'instance/hostname': 'server.project-bar.local', + 'instance/zone': 'bar/baz', +} + +GCE_META_ENCODING = { + 'instance/id': '12345', + 'instance/hostname': 'server.project-baz.local', + 'instance/zone': 'baz/bang', + 'instance/attributes/user-data': b64encode('/bin/echo baz\n'), + 'instance/attributes/user-data-encoding': 'base64', } HEADERS = {'X-Google-Metadata-Request': 'True'} MD_URL_RE = re.compile(r'http://metadata.google.internal./computeMetadata/v1/.*') -def _request_callback(method, uri, headers): - url_path = urlparse(uri).path - if url_path.startswith('/computeMetadata/v1/'): - path = url_path.split('/computeMetadata/v1/')[1:][0] - else: - path = None - if path in GCE_META: - return (200, headers, GCE_META.get(path)) - else: - return (404, headers, '') +def _new_request_callback(gce_meta=None): + if not gce_meta: + gce_meta = GCE_META + + def _request_callback(method, uri, headers): + url_path = urlparse(uri).path + if url_path.startswith('/computeMetadata/v1/'): + path = url_path.split('/computeMetadata/v1/')[1:][0] + else: + path = None + if path in gce_meta: + return (200, headers, gce_meta.get(path)) + else: + return (404, headers, '') + + return _request_callback class TestDataSourceGCE(test_helpers.HttprettyTestCase): @@ -67,7 +84,7 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): def test_connection(self): httpretty.register_uri( httpretty.GET, MD_URL_RE, - body=_request_callback) + body=_new_request_callback()) success = self.ds.get_data() self.assertTrue(success) @@ -79,7 +96,7 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): def test_metadata(self): httpretty.register_uri( httpretty.GET, MD_URL_RE, - body=_request_callback) + body=_new_request_callback()) self.ds.get_data() self.assertEqual(GCE_META.get('instance/hostname'), @@ -103,7 +120,7 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): def test_metadata_partial(self): httpretty.register_uri( httpretty.GET, MD_URL_RE, - body=_request_callback) + body=_new_request_callback(GCE_META_PARTIAL)) self.ds.get_data() self.assertEqual(GCE_META_PARTIAL.get('instance/id'), @@ -111,3 +128,13 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): self.assertEqual(GCE_META_PARTIAL.get('instance/hostname'), self.ds.get_hostname()) + + @httpretty.activate + def test_metadata_encoding(self): + httpretty.register_uri( + httpretty.GET, MD_URL_RE, + body=_new_request_callback(GCE_META_ENCODING)) + self.ds.get_data() + + decoded = b64decode(GCE_META_ENCODING.get('instance/attributes/user-data')) + self.assertEqual(decoded, self.ds.get_userdata_raw()) -- cgit v1.2.3 From c8ab70b9413e3d8d0f240d968023258b8a0970e6 Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Tue, 6 Jan 2015 11:41:05 -0500 Subject: Corrected errant logging message. --- cloudinit/sources/DataSourceGCE.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cloudinit/sources/DataSourceGCE.py b/cloudinit/sources/DataSourceGCE.py index e6f3651c..92e5a28e 100644 --- a/cloudinit/sources/DataSourceGCE.py +++ b/cloudinit/sources/DataSourceGCE.py @@ -29,7 +29,6 @@ BUILTIN_DS_CONFIG = { } REQUIRED_FIELDS = ('instance-id', 'availability-zone', 'local-hostname') - class DataSourceGCE(sources.DataSource): def __init__(self, sys_cfg, distro, paths): sources.DataSource.__init__(self, sys_cfg, distro, paths) @@ -104,11 +103,12 @@ class DataSourceGCE(sources.DataSource): lines = self.metadata['public-keys'].splitlines() self.metadata['public-keys'] = [self._trim_key(k) for k in lines] - if self.metadata.get('user-data-encoding'): - if self.metadata['user-data-encoding'] == 'base64': + encoding = self.metadata.get('user-data-encoding') + if encoding: + if encoding == 'base64': self.metadata['user-data'] = b64decode(self.metadata['user-data']) else: - LOG.warn('user-data-encoding: unknown encoding specified', None, None) + LOG.warn('unknown user-data-encoding: %s, ignoring', encoding) return found -- cgit v1.2.3 From 4de52eb92333245f2c88e386d57c16547b89ab97 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Tue, 6 Jan 2015 11:46:50 -0500 Subject: pep8 --- tests/unittests/test_datasource/test_gce.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unittests/test_datasource/test_gce.py b/tests/unittests/test_datasource/test_gce.py index 957747ef..e2449ba8 100644 --- a/tests/unittests/test_datasource/test_gce.py +++ b/tests/unittests/test_datasource/test_gce.py @@ -33,7 +33,7 @@ GCE_META = { 'project/attributes/sshKeys': 'user:ssh-rsa AA2..+aRD0fyVw== root@server', 'instance/hostname': 'server.project-foo.local', 'instance/attributes/user-data': '/bin/echo foo\n', - 'instance/attributes/user-data-encoding':'', + 'instance/attributes/user-data-encoding': '', } GCE_META_PARTIAL = { @@ -51,7 +51,8 @@ GCE_META_ENCODING = { } HEADERS = {'X-Google-Metadata-Request': 'True'} -MD_URL_RE = re.compile(r'http://metadata.google.internal./computeMetadata/v1/.*') +MD_URL_RE = re.compile( + r'http://metadata.google.internal./computeMetadata/v1/.*') def _new_request_callback(gce_meta=None): @@ -136,5 +137,6 @@ class TestDataSourceGCE(test_helpers.HttprettyTestCase): body=_new_request_callback(GCE_META_ENCODING)) self.ds.get_data() - decoded = b64decode(GCE_META_ENCODING.get('instance/attributes/user-data')) + decoded = b64decode( + GCE_META_ENCODING.get('instance/attributes/user-data')) self.assertEqual(decoded, self.ds.get_userdata_raw()) -- cgit v1.2.3 From b8eb056fd7fda5f50f07d7c0a0bc65c67d770f5e Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Tue, 6 Jan 2015 12:09:00 -0500 Subject: remove the user-data-encoding from test meta-data just so we don't come to rely on it being set to 'base64' or ''. rather the default case is that it wont be present at all. --- tests/unittests/test_datasource/test_gce.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unittests/test_datasource/test_gce.py b/tests/unittests/test_datasource/test_gce.py index e2449ba8..89251b0e 100644 --- a/tests/unittests/test_datasource/test_gce.py +++ b/tests/unittests/test_datasource/test_gce.py @@ -33,7 +33,6 @@ GCE_META = { 'project/attributes/sshKeys': 'user:ssh-rsa AA2..+aRD0fyVw== root@server', 'instance/hostname': 'server.project-foo.local', 'instance/attributes/user-data': '/bin/echo foo\n', - 'instance/attributes/user-data-encoding': '', } GCE_META_PARTIAL = { -- cgit v1.2.3