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)
def test_ntp_handler_schema_validation_warns_invalid_key_present( self, m_select): """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"] } } for distro in cc_ntp.distros: if distro != "alpine": mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig["confpath"] m_select.return_value = ntpconfig cc_ntp.handle("cc_ntp", invalid_config, mycloud, None, []) self.assertIn( "Invalid cloud-config provided:\nntp: Additional" " properties are not allowed ('invalidkey' was" " unexpected)", self.logs.getvalue(), ) self.assertEqual( "servers []\npools ['0.mycompany.pool.ntp.org']\n", util.load_file(confpath), )
def test_ntp_handler_schema_validation_warns_of_duplicates(self, m_select): """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"], } } for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig["confpath"] m_select.return_value = ntpconfig cc_ntp.handle("cc_ntp", invalid_config, mycloud, None, []) self.assertIn( "Invalid cloud-config provided:\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(), ) self.assertEqual( "servers ['10.0.0.1', '10.0.0.1']\n" "pools ['0.mypool.org', '0.mypool.org']\n", util.load_file(confpath), )
def test_ntp_handler(self): """Test ntp handler renders ubuntu ntp.conf template""" pools = ['0.mycompany.pool.ntp.org'] servers = ['192.168.23.3'] cfg = { 'ntp': { 'pools': pools, 'servers': servers, } } mycloud = self._get_cloud('ubuntu') side_effect = [NTP_TEMPLATE.lstrip()] with mock.patch.object(util, 'which', return_value=None): with mock.patch.object(os.path, 'exists'): with mock.patch.object(util, 'write_file') as mockwrite: with mock.patch.object(util, 'load_file', side_effect=side_effect): with mock.patch.object(os.path, 'isfile', return_value=True): with mock.patch.object(util, 'rename'): cc_ntp.handle("notimportant", cfg, mycloud, LOG, None) mockwrite.assert_called_once_with( '/etc/ntp.conf', NTP_EXPECTED_UBUNTU, mode=420)
def test_ntp_handler_schema_validation_warns_of_duplicates(self, m_select): """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'] } } for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig cc_ntp.handle('cc_ntp', invalid_config, mycloud, 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()) self.assertEqual( "servers ['10.0.0.1', '10.0.0.1']\n" "pools ['0.mypool.org', '0.mypool.org']\n", util.load_file(confpath))
def test_ntp_handler_schema_validation_allows_empty_ntp_config(self, m_select): """Ntp schema validation allows for an empty ntp: configuration.""" valid_empty_configs = [{'ntp': {}}, {'ntp': None}] for valid_empty_config in valid_empty_configs: for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig cc_ntp.handle('cc_ntp', valid_empty_config, mycloud, None, []) if distro == 'alpine': # _mock_ntp_client_config call above did not specify a # client value and so it defaults to "ntp" which on # Alpine Linux only supports servers and not pools. servers = cc_ntp.generate_server_names(mycloud.distro.name) self.assertEqual( "servers {0}\npools []\n".format(servers), util.load_file(confpath)) else: pools = cc_ntp.generate_server_names(mycloud.distro.name) self.assertEqual( "servers []\npools {0}\n".format(pools), util.load_file(confpath)) self.assertNotIn('Invalid config:', self.logs.getvalue())
def test_ntp_handler_enabled_false(self, m_select): """Test ntp handler does not run if enabled: false """ cfg = {'ntp': {'enabled': False}} for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) cc_ntp.handle('notimportant', cfg, mycloud, None, None) self.assertEqual(0, m_select.call_count)
def test_ntp_user_provided_config_with_template(self, m_install, m_reload): custom = r'\n#MyCustomTemplate' user_template = NTP_TEMPLATE + custom confpath = os.path.join(self.new_root, 'etc/myntp/myntp.conf') cfg = { 'ntp': { 'pools': ['mypool.org'], 'ntp_client': 'myntpd', 'config': { 'check_exe': 'myntpd', 'confpath': confpath, 'packages': ['myntp'], 'service_name': 'myntp', 'template': user_template, } } } for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR' with mock.patch(mock_path, self.new_root): cc_ntp.handle('notimportant', cfg, mycloud, None, None) self.assertEqual( "servers []\npools ['mypool.org']\n%s" % custom, util.load_file(confpath))
def test_ntp_user_provided_config_template_only(self, m_select, m_install, m_schema): """Test custom template for default client""" custom = r'\n#MyCustomTemplate' user_template = NTP_TEMPLATE + custom client = 'chrony' cfg = { 'pools': ['mypool.org'], 'ntp_client': client, 'config': { 'template': user_template, } } expected_merged_cfg = { 'check_exe': 'chronyd', 'confpath': '{tmpdir}/client.conf'.format(tmpdir=self.new_root), 'template_name': 'client.conf', 'template': user_template, 'service_name': 'chrony', 'packages': ['chrony'] } for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(client=client, distro=distro) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR' with mock.patch(mock_path, self.new_root): cc_ntp.handle('notimportant', {'ntp': cfg}, mycloud, None, None) self.assertEqual("servers []\npools ['mypool.org']\n%s" % custom, util.load_file(confpath)) m_schema.assert_called_with(expected_merged_cfg)
def test_no_ntpcfg_does_nothing(self): """When no ntp section is defined handler logs a warning and noops.""" cc_ntp.handle('cc_ntp', {}, None, None, []) self.assertEqual( 'DEBUG: Skipping module named cc_ntp, ' 'not present or disabled by cfg\n', self.logs.getvalue())
def test_ntp_handler(self): """Test ntp handler renders ubuntu ntp.conf template""" pools = ['0.mycompany.pool.ntp.org'] servers = ['192.168.23.3'] cfg = { 'ntp': { 'pools': pools, 'servers': servers, } } mycloud = self._get_cloud('ubuntu') side_effect = [NTP_TEMPLATE.lstrip()] with mock.patch.object(util, 'which', return_value=None): with mock.patch.object(os.path, 'exists'): with mock.patch.object(util, 'write_file') as mockwrite: with mock.patch.object(util, 'load_file', side_effect=side_effect): with mock.patch.object(os.path, 'isfile', return_value=True): with mock.patch.object(util, 'rename'): cc_ntp.handle("notimportant", cfg, mycloud, LOG, None) mockwrite.assert_called_once_with('/etc/ntp.conf', NTP_EXPECTED_UBUNTU, mode=420)
def test_ntp_handler_real_distro_templates(self): """Test ntp handler renders the shipped distro ntp.conf templates.""" pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org'] servers = ['192.168.23.3', '192.168.23.4'] cfg = {'ntp': {'pools': pools, 'servers': servers}} ntp_conf = self.tmp_path('ntp.conf', self.new_root) # Doesn't exist for distro in ('debian', 'ubuntu', 'fedora', 'rhel', 'sles'): mycloud = self._get_cloud(distro) root_dir = dirname(dirname(os.path.realpath(util.__file__))) tmpl_file = os.path.join('{0}/templates/ntp.conf.{1}.tmpl'.format( root_dir, distro)) # Create a copy in our tmp_dir shutil.copy( tmpl_file, os.path.join(self.new_root, 'ntp.conf.%s.tmpl' % distro)) with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): with mock.patch.object(util, 'which', return_value=[True]): cc_ntp.handle('notimportant', cfg, mycloud, None, None) content = util.read_file_or_url('file://' + ntp_conf).contents expected_servers = '\n'.join( ['server {0} iburst'.format(server) for server in servers]) self.assertIn( expected_servers, content.decode(), 'failed to render ntp.conf for distro:{0}'.format(distro)) expected_pools = '\n'.join( ['pool {0} iburst'.format(pool) for pool in pools]) self.assertIn( expected_pools, content.decode(), 'failed to render ntp.conf for distro:{0}'.format(distro))
def test_ntp_user_provided_config_with_template(self, m_install): custom = r"\n#MyCustomTemplate" user_template = NTP_TEMPLATE + custom confpath = os.path.join(self.new_root, "etc/myntp/myntp.conf") cfg = { "ntp": { "pools": ["mypool.org"], "ntp_client": "myntpd", "config": { "check_exe": "myntpd", "confpath": confpath, "packages": ["myntp"], "service_name": "myntp", "template": user_template, }, } } for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) mock_path = "cloudinit.config.cc_ntp.temp_utils._TMPDIR" with mock.patch(mock_path, self.new_root): cc_ntp.handle("notimportant", cfg, mycloud, None, None) self.assertEqual( "servers []\npools ['mypool.org']\n%s" % custom, util.load_file(confpath), )
def test_ntp_handler_schema_validation_warns_invalid_key_present( self, m_select): """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'] } } for distro in cc_ntp.distros: if distro != 'alpine': mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig cc_ntp.handle('cc_ntp', invalid_config, mycloud, None, []) self.assertIn( "Invalid config:\nntp: Additional properties are not " "allowed ('invalidkey' was unexpected)", self.logs.getvalue()) self.assertEqual( "servers []\npools ['0.mycompany.pool.ntp.org']\n", util.load_file(confpath))
def test_ntp_the_whole_package(self, m_sysd, m_select): """Test enabled config renders template, and restarts service """ cfg = {'ntp': {'enabled': True}} for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] service_name = ntpconfig['service_name'] m_select.return_value = ntpconfig pools = cc_ntp.generate_server_names(mycloud.distro.name) # force uses systemd path m_sysd.return_value = True with mock.patch('cloudinit.config.cc_ntp.util') as m_util: # allow use of util.mergemanydict m_util.mergemanydict.side_effect = util.mergemanydict # default client is present m_util.which.return_value = True # use the config 'enabled' value m_util.is_false.return_value = util.is_false( cfg['ntp']['enabled']) cc_ntp.handle('notimportant', cfg, mycloud, None, None) m_util.subp.assert_called_with( ['systemctl', 'reload-or-restart', service_name], capture=True) self.assertEqual("servers []\npools {0}\n".format(pools), util.load_file(confpath))
def test_ntp_custom_client_overrides_installed_clients( self, m_which, m_tmpfn, m_write): """Test user client is installed despite other clients present """ client = 'ntpdate' cfg = {'ntp': {'ntp_client': client}} for distro in cc_ntp.distros: # client is not installed m_which.side_effect = iter([None]) mycloud = self._get_cloud(distro) with mock.patch.object(mycloud.distro, 'install_packages') as m_install: cc_ntp.handle('notimportant', cfg, mycloud, None, None) m_install.assert_called_with([client]) m_which.assert_called_with(client)
def test_ntp_handler_schema_validation_allows_empty_ntp_config( self, m_select): """Ntp schema validation allows for an empty ntp: configuration.""" valid_empty_configs = [{'ntp': {}}, {'ntp': None}] for valid_empty_config in valid_empty_configs: for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig cc_ntp.handle('cc_ntp', valid_empty_config, mycloud, None, []) pools = cc_ntp.generate_server_names(mycloud.distro.name) self.assertEqual("servers []\npools {0}\n".format(pools), util.load_file(confpath)) self.assertNotIn('Invalid config:', self.logs.getvalue())
def test_ntp_handler_timesyncd(self, m_select): """Test ntp handler configures timesyncd""" servers = ['192.168.2.1', '192.168.2.2'] pools = ['0.mypool.org'] cfg = {'ntp': {'servers': servers, 'pools': pools}} client = 'systemd-timesyncd' for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro, client=client) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig cc_ntp.handle('cc_ntp', cfg, mycloud, None, []) self.assertEqual( "[Time]\nNTP=192.168.2.1 192.168.2.2 0.mypool.org \n", util.load_file(confpath))
def test_ntp_handler_timesyncd(self, m_select): """Test ntp handler configures timesyncd""" servers = ["192.168.2.1", "192.168.2.2"] pools = ["0.mypool.org"] cfg = {"ntp": {"servers": servers, "pools": pools}} client = "systemd-timesyncd" for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro, client=client) confpath = ntpconfig["confpath"] m_select.return_value = ntpconfig cc_ntp.handle("cc_ntp", cfg, mycloud, None, []) self.assertEqual( "[Time]\nNTP=192.168.2.1 192.168.2.2 0.mypool.org \n", util.load_file(confpath), )
def test_ntp_handler_mocked_template(self): """Test ntp handler renders ubuntu ntp.conf template.""" pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org'] servers = ['192.168.23.3', '192.168.23.4'] cfg = {'ntp': {'pools': pools, 'servers': servers}} mycloud = self._get_cloud('ubuntu') ntp_conf = self.tmp_path('ntp.conf', self.new_root) # Doesn't exist # Create ntp.conf.tmpl 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): with mock.patch.object(util, 'which', return_value=None): cc_ntp.handle('notimportant', cfg, mycloud, None, None) content = util.read_file_or_url('file://' + ntp_conf).contents self.assertEqual('servers {0}\npools {1}\n'.format(servers, pools), content.decode())
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_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, m_sel): """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]}} for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] m_sel.return_value = ntpconfig cc_ntp.handle('cc_ntp', invalid_config, mycloud, 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()) self.assertEqual("servers ['valid', None]\npools [123]\n", util.load_file(confpath))
def test_ntp_handler_schema_validation_warns_of_non_array_type( self, m_select): """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'}} for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig['confpath'] m_select.return_value = ntpconfig cc_ntp.handle('cc_ntp', invalid_config, mycloud, 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()) self.assertEqual("servers non-array\npools 123\n", util.load_file(confpath))
def test_ntp_the_whole_package(self, m_sysd, m_select, m_subp, m_dsubp): """Test enabled config renders template, and restarts service""" cfg = {"ntp": {"enabled": True}} for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(distro=distro) confpath = ntpconfig["confpath"] service_name = ntpconfig["service_name"] m_select.return_value = ntpconfig hosts = cc_ntp.generate_server_names(mycloud.distro.name) uses_systemd = True expected_service_call = [ "systemctl", "reload-or-restart", service_name, ] expected_content = "servers []\npools {0}\n".format(hosts) if distro == "alpine": uses_systemd = False expected_service_call = ["rc-service", service_name, "restart"] # _mock_ntp_client_config call above did not specify a client # value and so it defaults to "ntp" which on Alpine Linux only # supports servers and not pools. expected_content = "servers {0}\npools []\n".format(hosts) m_sysd.return_value = uses_systemd with mock.patch("cloudinit.config.cc_ntp.util") as m_util: # allow use of util.mergemanydict m_util.mergemanydict.side_effect = util.mergemanydict # default client is present m_subp.which.return_value = True # use the config 'enabled' value m_util.is_false.return_value = util.is_false( cfg["ntp"]["enabled"]) cc_ntp.handle("notimportant", cfg, mycloud, None, None) m_dsubp.subp.assert_called_with(expected_service_call, capture=True) self.assertEqual(expected_content, util.load_file(confpath))
def test_ntp_handler_mocked_template_snappy(self, m_util): """Test ntp handler renders timesycnd.conf template on snappy.""" pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org'] servers = ['192.168.23.3', '192.168.23.4'] cfg = {'ntp': {'pools': pools, 'servers': servers}} mycloud = self._get_cloud('ubuntu') m_util.system_is_snappy.return_value = True # Create timesyncd.conf.tmpl tsyncd_conf = self.tmp_path("timesyncd.conf", self.new_root) template = '{0}.tmpl'.format(tsyncd_conf) with open(template, 'wb') as stream: stream.write(TIMESYNCD_TEMPLATE) with mock.patch('cloudinit.config.cc_ntp.TIMESYNCD_CONF', tsyncd_conf): cc_ntp.handle('notimportant', cfg, mycloud, None, None) content = util.read_file_or_url('file://' + tsyncd_conf).contents self.assertEqual( "[Time]\nNTP=%s %s \n" % (" ".join(servers), " ".join(pools)), content.decode())
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_user_provided_config_template_only(self, m_select, m_install, m_schema): """Test custom template for default client""" custom = r"\n#MyCustomTemplate" user_template = NTP_TEMPLATE + custom client = "chrony" cfg = { "pools": ["mypool.org"], "ntp_client": client, "config": { "template": user_template, }, } expected_merged_cfg = { "check_exe": "chronyd", "confpath": "{tmpdir}/client.conf".format(tmpdir=self.new_root), "template_name": "client.conf", "template": user_template, "service_name": "chrony", "packages": ["chrony"], } for distro in cc_ntp.distros: mycloud = self._get_cloud(distro) ntpconfig = self._mock_ntp_client_config(client=client, distro=distro) confpath = ntpconfig["confpath"] m_select.return_value = ntpconfig mock_path = "cloudinit.config.cc_ntp.temp_utils._TMPDIR" with mock.patch(mock_path, self.new_root): cc_ntp.handle("notimportant", {"ntp": cfg}, mycloud, None, None) self.assertEqual( "servers []\npools ['mypool.org']\n%s" % custom, util.load_file(confpath), ) m_schema.assert_called_with(expected_merged_cfg)
def test_no_ntpcfg_does_nothing(self, mock_util): cc = self._get_cloud('ubuntu') cc.distro = mock.MagicMock() cc_ntp.handle('cc_ntp', {}, cc, LOG, []) self.assertFalse(cc.distro.install_packages.called) self.assertFalse(mock_util.subp.called)