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),
            )
Example #4
0
    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)
Example #5
0
    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())
Example #7
0
 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))
Example #9
0
 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))
Example #13
0
 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),
         )
Example #14
0
    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))
Example #15
0
 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))
Example #16
0
 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)
Example #17
0
 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())
Example #18
0
 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))
Example #19
0
 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),
         )
Example #20
0
    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)
Example #22
0
 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)
Example #23
0
    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))
Example #24
0
    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))
Example #25
0
    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)
Example #28
0
 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)
Example #30
0
 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)