diff options
author | Chad Smith <chad.smith@canonical.com> | 2017-05-25 11:04:55 -0600 |
---|---|---|
committer | Scott Moser <smoser@brickies.net> | 2017-05-31 16:43:12 -0400 |
commit | 0a448dd034883c07f85091dbfc9117de7227eb8d (patch) | |
tree | fe9610a93f165324fbf343d6748d2964e89f3ef6 /tests/unittests/test_handler/test_handler_ntp.py | |
parent | 00b678c61a54f176625d3f937971215faf6af2cd (diff) | |
download | vyos-cloud-init-0a448dd034883c07f85091dbfc9117de7227eb8d.tar.gz vyos-cloud-init-0a448dd034883c07f85091dbfc9117de7227eb8d.zip |
ntp: Add schema definition and passive schema validation.
cloud-config files are very flexible and permissive.
This adds a jsonsschema definition to the cc_ntp module and validation
functions in cloudinit/config/schema which will log warnings about
invalid configuration values in the ntp section.
A cmdline tools/cloudconfig-schema is added which can be used in our dev
environments to quickly attempt to exercise the ntp schema.
It is also exposed as a main in cloudinit.config.schema.
(python3 -m cloudinit.config.schema)
LP: #1692916
Diffstat (limited to 'tests/unittests/test_handler/test_handler_ntp.py')
-rw-r--r-- | tests/unittests/test_handler/test_handler_ntp.py | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/tests/unittests/test_handler/test_handler_ntp.py b/tests/unittests/test_handler/test_handler_ntp.py index bc4277b7..6cafa63d 100644 --- a/tests/unittests/test_handler/test_handler_ntp.py +++ b/tests/unittests/test_handler/test_handler_ntp.py @@ -212,4 +212,113 @@ class TestNtp(FilesystemMockingTestCase): 'Skipping module named cc_ntp, not present or disabled by cfg\n', self.logs.getvalue()) + def test_ntp_handler_schema_validation_allows_empty_ntp_config(self): + """Ntp schema validation allows for an empty ntp: configuration.""" + invalid_config = {'ntp': {}} + distro = 'ubuntu' + cc = self._get_cloud(distro) + ntp_conf = os.path.join(self.new_root, 'ntp.conf') + with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream: + stream.write(NTP_TEMPLATE) + with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): + cc_ntp.handle('cc_ntp', invalid_config, cc, None, []) + self.assertNotIn('Invalid config:', self.logs.getvalue()) + with open(ntp_conf) as stream: + content = stream.read() + default_pools = [ + "{0}.{1}.pool.ntp.org".format(x, distro) + for x in range(0, cc_ntp.NR_POOL_SERVERS)] + self.assertEqual( + "servers []\npools {0}\n".format(default_pools), + content) + + def test_ntp_handler_schema_validation_warns_non_string_item_type(self): + """Ntp schema validation warns of non-strings in pools or servers. + + Schema validation is not strict, so ntp config is still be rendered. + """ + invalid_config = {'ntp': {'pools': [123], 'servers': ['valid', None]}} + cc = self._get_cloud('ubuntu') + ntp_conf = os.path.join(self.new_root, 'ntp.conf') + with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream: + stream.write(NTP_TEMPLATE) + with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): + cc_ntp.handle('cc_ntp', invalid_config, cc, None, []) + self.assertIn( + "Invalid config:\nntp.pools.0: 123 is not of type 'string'\n" + "ntp.servers.1: None is not of type 'string'", + self.logs.getvalue()) + with open(ntp_conf) as stream: + content = stream.read() + self.assertEqual("servers ['valid', None]\npools [123]\n", content) + + def test_ntp_handler_schema_validation_warns_of_non_array_type(self): + """Ntp schema validation warns of non-array pools or servers types. + + Schema validation is not strict, so ntp config is still be rendered. + """ + invalid_config = {'ntp': {'pools': 123, 'servers': 'non-array'}} + cc = self._get_cloud('ubuntu') + ntp_conf = os.path.join(self.new_root, 'ntp.conf') + with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream: + stream.write(NTP_TEMPLATE) + with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): + cc_ntp.handle('cc_ntp', invalid_config, cc, None, []) + self.assertIn( + "Invalid config:\nntp.pools: 123 is not of type 'array'\n" + "ntp.servers: 'non-array' is not of type 'array'", + self.logs.getvalue()) + with open(ntp_conf) as stream: + content = stream.read() + self.assertEqual("servers non-array\npools 123\n", content) + + def test_ntp_handler_schema_validation_warns_invalid_key_present(self): + """Ntp schema validation warns of invalid keys present in ntp config. + + Schema validation is not strict, so ntp config is still be rendered. + """ + invalid_config = { + 'ntp': {'invalidkey': 1, 'pools': ['0.mycompany.pool.ntp.org']}} + cc = self._get_cloud('ubuntu') + ntp_conf = os.path.join(self.new_root, 'ntp.conf') + with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream: + stream.write(NTP_TEMPLATE) + with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): + cc_ntp.handle('cc_ntp', invalid_config, cc, None, []) + self.assertIn( + "Invalid config:\nntp: Additional properties are not allowed " + "('invalidkey' was unexpected)", + self.logs.getvalue()) + with open(ntp_conf) as stream: + content = stream.read() + self.assertEqual( + "servers []\npools ['0.mycompany.pool.ntp.org']\n", + content) + + def test_ntp_handler_schema_validation_warns_of_duplicates(self): + """Ntp schema validation warns of duplicates in servers or pools. + + Schema validation is not strict, so ntp config is still be rendered. + """ + invalid_config = { + 'ntp': {'pools': ['0.mypool.org', '0.mypool.org'], + 'servers': ['10.0.0.1', '10.0.0.1']}} + cc = self._get_cloud('ubuntu') + ntp_conf = os.path.join(self.new_root, 'ntp.conf') + with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream: + stream.write(NTP_TEMPLATE) + with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): + cc_ntp.handle('cc_ntp', invalid_config, cc, None, []) + self.assertIn( + "Invalid config:\nntp.pools: ['0.mypool.org', '0.mypool.org'] has " + "non-unique elements\nntp.servers: ['10.0.0.1', '10.0.0.1'] has " + "non-unique elements", + self.logs.getvalue()) + with open(ntp_conf) as stream: + content = stream.read() + self.assertEqual( + "servers ['10.0.0.1', '10.0.0.1']\n" + "pools ['0.mypool.org', '0.mypool.org']\n", + content) + # vi: ts=4 expandtab |