def test_ntp_conf_contents_match(self): """Test rendered contents of /etc/ntp.conf for ubuntu""" 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()] # work backwards from util.write_file and mock out call path # write_ntp_config_template() # cloud.get_template_filename() # os.path.isfile() # templater.render_to_file() # templater.render_from_file() # util.load_file() # util.write_file() # 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.write_ntp_config_template( cfg.get('ntp'), mycloud) mockwrite.assert_called_once_with('/etc/ntp.conf', NTP_EXPECTED_UBUNTU, mode=420)
def test_ntp_conf_contents_match(self): """Test rendered contents of /etc/ntp.conf for ubuntu""" 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()] # work backwards from util.write_file and mock out call path # write_ntp_config_template() # cloud.get_template_filename() # os.path.isfile() # templater.render_to_file() # templater.render_from_file() # util.load_file() # util.write_file() # 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.write_ntp_config_template(cfg.get('ntp'), mycloud) mockwrite.assert_called_once_with( '/etc/ntp.conf', NTP_EXPECTED_UBUNTU, mode=420)
def test_ntp_handler_real_distro_ntp_templates(self): """Test ntp handler renders the shipped distro ntp client templates.""" pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org'] servers = ['192.168.23.3', '192.168.23.4'] for client in ['ntp', 'systemd-timesyncd', 'chrony']: for distro in cc_ntp.distros: distro_cfg = cc_ntp.distro_ntp_client_configs(distro) ntpclient = distro_cfg[client] confpath = ( os.path.join(self.new_root, ntpclient.get('confpath')[1:])) template = ntpclient.get('template_name') # find sourcetree template file root_dir = ( dirname(dirname(os.path.realpath(util.__file__))) + '/templates') source_fn = self._get_template_path(template, distro, basepath=root_dir) template_fn = self._get_template_path(template, distro) # don't fail if cloud-init doesn't have a template for # a distro,client pair if not os.path.exists(source_fn): continue # Create a copy in our tmp_dir shutil.copy(source_fn, template_fn) cc_ntp.write_ntp_config_template(distro, servers=servers, pools=pools, path=confpath, template_fn=template_fn) content = util.load_file(confpath) if client in ['ntp', 'chrony']: content_lines = content.splitlines() expected_servers = self._get_expected_servers(servers, distro, client) print('distro=%s client=%s' % (distro, client)) for sline in expected_servers: self.assertIn(sline, content_lines, ('failed to render {0} conf' ' for distro:{1}'.format(client, distro))) expected_pools = self._get_expected_pools(pools, distro, client) if expected_pools != []: for pline in expected_pools: self.assertIn(pline, content_lines, ('failed to render {0} conf' ' for distro:{1}'.format(client, distro))) elif client == 'systemd-timesyncd': expected_servers = self._get_expected_servers(servers, distro, client) expected_pools = self._get_expected_pools(pools, distro, client) expected_content = ( "# cloud-init generated file\n" + "# See timesyncd.conf(5) for details.\n\n" + "[Time]\nNTP=%s %s \n" % (expected_servers, expected_pools)) self.assertEqual(expected_content, content)
def test_defaults_pools_empty_lists_sles(self): """write_ntp_config_template defaults opensuse pools upon empty config. When both pools and servers are empty, default NR_POOL_SERVERS get configured. """ distro = "sles" default_pools = cc_ntp.generate_server_names(distro) (confpath, template_fn) = self._generate_template() cc_ntp.write_ntp_config_template( distro, servers=[], pools=[], path=confpath, template_fn=template_fn, template=None, ) for pool in default_pools: self.assertIn("opensuse", pool) self.assertEqual( "servers []\npools {0}\n".format(default_pools), util.load_file(confpath), ) self.assertIn( "Adding distro default ntp pool servers: {0}".format( ",".join(default_pools)), self.logs.getvalue(), )
def test_timesyncd_template(self): """Test timesycnd template is correct""" pools = ['0.mycompany.pool.ntp.org', '3.mycompany.pool.ntp.org'] servers = ['192.168.23.3', '192.168.23.4'] (confpath, template_fn) = self._generate_template( template=TIMESYNCD_TEMPLATE) cc_ntp.write_ntp_config_template('ubuntu', servers=servers, pools=pools, path=confpath, template_fn=template_fn, template=None) self.assertEqual( "[Time]\nNTP=%s %s \n" % (" ".join(servers), " ".join(pools)), util.load_file(confpath))
def test_write_ntp_config_template_uses_ntp_conf_distro_no_servers(self): """write_ntp_config_template reads from $client.conf.distro.tmpl""" servers = [] pools = ['10.0.0.1', '10.0.0.2'] (confpath, template_fn) = self._generate_template() mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR' with mock.patch(mock_path, self.new_root): cc_ntp.write_ntp_config_template('ubuntu', servers=servers, pools=pools, path=confpath, template_fn=template_fn, template=None) self.assertEqual("servers []\npools ['10.0.0.1', '10.0.0.2']\n", util.load_file(confpath))
def ntp_conf_render(self, distro): """ntp_conf_render Test rendering of a ntp.conf from template for a given distro """ cfg = {'ntp': {}} mycloud = self._get_cloud(distro) distro_names = cc_ntp.generate_server_names(distro) with mock.patch.object(templater, 'render_to_file') as mocktmpl: with mock.patch.object(os.path, 'isfile', return_value=True): with mock.patch.object(util, 'rename'): cc_ntp.write_ntp_config_template(cfg, mycloud) mocktmpl.assert_called_once_with( ('/etc/cloud/templates/ntp.conf.%s.tmpl' % distro), '/etc/ntp.conf', {'servers': [], 'pools': distro_names})
def test_write_ntp_config_template_from_ntp_conf_tmpl_with_servers(self): """write_ntp_config_template reads content from ntp.conf.tmpl. It reads ntp.conf.tmpl if present and renders the value from servers key. When no pools key is defined, template is rendered using an empty list for pools. """ distro = 'ubuntu' cfg = {'servers': ['192.168.2.1', '192.168.2.2']} mycloud = self._get_cloud(distro) 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): cc_ntp.write_ntp_config_template(cfg, mycloud, ntp_conf) content = util.read_file_or_url('file://' + ntp_conf).contents self.assertEqual("servers ['192.168.2.1', '192.168.2.2']\npools []\n", content.decode())
def test_write_ntp_config_template_defaults_pools_w_empty_lists(self): """write_ntp_config_template defaults pools servers upon empty config. When both pools and servers are empty, default NR_POOL_SERVERS get configured. """ distro = 'ubuntu' pools = cc_ntp.generate_server_names(distro) servers = [] (confpath, template_fn) = self._generate_template() mock_path = 'cloudinit.config.cc_ntp.temp_utils._TMPDIR' with mock.patch(mock_path, self.new_root): cc_ntp.write_ntp_config_template(distro, servers=servers, pools=pools, path=confpath, template_fn=template_fn, template=None) self.assertEqual("servers []\npools {0}\n".format(pools), util.load_file(confpath))
def ntp_conf_render(self, distro): """ntp_conf_render Test rendering of a ntp.conf from template for a given distro """ cfg = {'ntp': {}} mycloud = self._get_cloud(distro) distro_names = cc_ntp.generate_server_names(distro) with mock.patch.object(templater, 'render_to_file') as mocktmpl: with mock.patch.object(os.path, 'isfile', return_value=True): with mock.patch.object(util, 'rename'): cc_ntp.write_ntp_config_template(cfg, mycloud) mocktmpl.assert_called_once_with( ('/etc/cloud/templates/ntp.conf.%s.tmpl' % distro), '/etc/ntp.conf', { 'servers': [], 'pools': distro_names })
def test_ntp_conf_custom_pools_and_server(self): distro = 'ubuntu' pools = ['0.mycompany.pool.ntp.org'] servers = ['192.168.23.3'] cfg = { 'ntp': { 'pools': pools, 'servers': servers, } } mycloud = self._get_cloud(distro) with mock.patch.object(templater, 'render_to_file') as mocktmpl: with mock.patch.object(os.path, 'isfile', return_value=True): with mock.patch.object(util, 'rename'): cc_ntp.write_ntp_config_template(cfg.get('ntp'), mycloud) mocktmpl.assert_called_once_with( ('/etc/cloud/templates/ntp.conf.%s.tmpl' % distro), '/etc/ntp.conf', {'servers': servers, 'pools': pools})
def test_write_ntp_config_template_uses_ntp_conf_distro_no_servers(self): """write_ntp_config_template reads content from ntp.conf.distro.tmpl. It reads ntp.conf.<distro>.tmpl before attempting ntp.conf.tmpl. It renders the value from the keys servers and pools. When no servers value is present, template is rendered using an empty list. """ distro = 'ubuntu' cfg = {'pools': ['10.0.0.1', '10.0.0.2']} mycloud = self._get_cloud(distro) ntp_conf = self.tmp_path('ntp.conf', self.new_root) # Doesn't exist # Create ntp.conf.tmpl which isn't read with open('{0}.tmpl'.format(ntp_conf), 'wb') as stream: stream.write(b'NOT READ: ntp.conf.<distro>.tmpl is primary') # Create ntp.conf.tmpl.<distro> with open('{0}.{1}.tmpl'.format(ntp_conf, distro), 'wb') as stream: stream.write(NTP_TEMPLATE) with mock.patch('cloudinit.config.cc_ntp.NTP_CONF', ntp_conf): cc_ntp.write_ntp_config_template(cfg, mycloud, ntp_conf) content = util.read_file_or_url('file://' + ntp_conf).contents self.assertEqual("servers []\npools ['10.0.0.1', '10.0.0.2']\n", content.decode())
def test_ntp_conf_custom_pools_and_server(self): distro = 'ubuntu' pools = ['0.mycompany.pool.ntp.org'] servers = ['192.168.23.3'] cfg = { 'ntp': { 'pools': pools, 'servers': servers, } } mycloud = self._get_cloud(distro) with mock.patch.object(templater, 'render_to_file') as mocktmpl: with mock.patch.object(os.path, 'isfile', return_value=True): with mock.patch.object(util, 'rename'): cc_ntp.write_ntp_config_template(cfg.get('ntp'), mycloud) mocktmpl.assert_called_once_with( ('/etc/cloud/templates/ntp.conf.%s.tmpl' % distro), '/etc/ntp.conf', { 'servers': servers, 'pools': pools })
def test_write_ntp_config_template_defaults_pools_empty_lists_sles(self): """write_ntp_config_template defaults pools servers upon empty config. When both pools and servers are empty, default NR_POOL_SERVERS get configured. """ distro = 'sles' mycloud = self._get_cloud(distro) 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): cc_ntp.write_ntp_config_template({}, mycloud, ntp_conf) content = util.read_file_or_url('file://' + ntp_conf).contents default_pools = [ "{0}.opensuse.pool.ntp.org".format(x) for x in range(0, cc_ntp.NR_POOL_SERVERS) ] self.assertEqual("servers []\npools {0}\n".format(default_pools), content.decode()) self.assertIn( "Adding distro default ntp pool servers: {0}".format( ",".join(default_pools)), self.logs.getvalue())
def test_ntp_handler_timesyncd(self, m_ntp_install): """Test ntp handler configures timesyncd""" m_ntp_install.return_value = False distro = 'ubuntu' cfg = { 'servers': ['192.168.2.1', '192.168.2.2'], 'pools': ['0.mypool.org'], } mycloud = self._get_cloud(distro) tsyncd_conf = self.tmp_path("timesyncd.conf", self.new_root) # Create timesyncd.conf.tmpl template = '{0}.tmpl'.format(tsyncd_conf) print(template) with open(template, 'wb') as stream: stream.write(TIMESYNCD_TEMPLATE) with mock.patch('cloudinit.config.cc_ntp.TIMESYNCD_CONF', tsyncd_conf): cc_ntp.write_ntp_config_template(cfg, mycloud, tsyncd_conf, template='timesyncd.conf') content = util.read_file_or_url('file://' + tsyncd_conf).contents self.assertEqual("[Time]\nNTP=192.168.2.1 192.168.2.2 0.mypool.org \n", content.decode())
def test_defaults_pools_empty_lists_sles(self): """write_ntp_config_template defaults opensuse pools upon empty config. When both pools and servers are empty, default NR_POOL_SERVERS get configured. """ distro = 'sles' default_pools = cc_ntp.generate_server_names(distro) (confpath, template_fn) = self._generate_template() cc_ntp.write_ntp_config_template(distro, servers=[], pools=[], path=confpath, template_fn=template_fn, template=None) content = util.read_file_or_url('file://' + confpath).contents for pool in default_pools: self.assertIn('opensuse', pool) self.assertEqual("servers []\npools {0}\n".format(default_pools), content.decode()) self.assertIn( "Adding distro default ntp pool servers: {0}".format( ",".join(default_pools)), self.logs.getvalue())