Example #1
0
    def update_setup(self, request):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if os.path.isfile(pwfile):
            with open(pwfile, "r") as fp:
                self.dm_password = fp.read().rstrip()
        else:
            pytest.skip("No directory manager password")
        self.updater = LDAPUpdate()
        self.ld = ipaldap.LDAPClient.from_hostname_secure(fqdn)
        self.ld.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
                            bind_password=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not os.path.isfile(os.path.join(self.testdir, "0_reset.update")):
            pytest.skip("Unable to find test update files")

        self.container_dn = DN(
            self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(
            self.updater._template_str(
                'uid=tuser, cn=test, cn=accounts, $SUFFIX'))

        def fin():
            if self.ld:
                self.ld.unbind()

        request.addfinalizer(fin)
Example #2
0
    def run(self):
        super(LDAPUpdater_NonUpgrade, self).run()
        api.Backend.ldap2.connect()
        options = self.options

        modified = False

        if options.schema_files:
            modified = schemaupdate.update_schema(
                options.schema_files,
                ldapi=True) or modified

        ld = LDAPUpdate(
            sub_dict={},
            ldapi=True)

        if not self.files:
            self.files = ld.get_all_files(UPDATES_DIR)

        modified = ld.update(self.files) or modified

        if modified:
            logger.info('Update complete')
        else:
            logger.info('Update complete, no data were modified')

        api.Backend.ldap2.disconnect()
Example #3
0
    def run(self):
        super(LDAPUpdater_NonUpgrade, self).run()
        api.Backend.ldap2.connect()
        options = self.options

        modified = False

        if options.schema_files:
            modified = schemaupdate.update_schema(
                options.schema_files,
                ldapi=True) or modified

        ld = LDAPUpdate(
            sub_dict={},
            ldapi=True)

        if not self.files:
            self.files = ld.get_all_files(UPDATES_DIR)

        modified = ld.update(self.files) or modified

        if modified:
            self.log.info('Update complete')
        else:
            self.log.info('Update complete, no data were modified')

        api.Backend.ldap2.disconnect()
Example #4
0
    def run(self):
        super(LDAPUpdater_NonUpgrade, self).run()
        options = self.options

        modified = False

        if options.update_schema:
            modified = schemaupdate.update_schema(
                options.schema_files,
                dm_password=self.dirman_password,
                live_run=not options.test) or modified

        ld = LDAPUpdate(
            dm_password=self.dirman_password,
            sub_dict={},
            live_run=not options.test,
            ldapi=options.ldapi,
            plugins=options.plugins or self.run_plugins)

        if not self.files:
            self.files = ld.get_all_files(UPDATES_DIR)

        modified = ld.update(self.files, ordered=True) or modified

        if modified and options.test:
            self.log.info('Update complete, changes to be made, test mode')
            return 2
Example #5
0
    def update(self, updatetype, dm_password, ldapi, live_run):
        """
        Execute all update plugins of type updatetype.
        """
        self.create_context(dm_password)
        kw = dict(live_run=live_run)
        result = []
        ld = LDAPUpdate(dm_password=dm_password,
                        sub_dict={},
                        live_run=live_run,
                        ldapi=ldapi)
        for update in self.order(updatetype):
            (restart, apply_now, res) = self.run(update.name, **kw)
            if restart:
                self.restart(dm_password, live_run)

            if apply_now:
                updates = {}
                for entry in res:
                    updates.update(entry)
                ld.update_from_dict(updates)
            elif res:
                result.extend(res)

        self.destroy_context()

        return result
Example #6
0
    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise nose.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password,
                                  sub_dict={},
                                  live_run=True)
        self.ld = ipaldap.IPAdmin(fqdn)
        self.ld.do_simple_bind(bindpw=self.dm_password)
        if ipautil.file_exists("0_reset.update"):
            self.testdir = "./"
        elif ipautil.file_exists("tests/test_install/0_reset.update"):
            self.testdir = "./tests/test_install/"
        else:
            raise nose.SkipTest("Unable to find test update files")

        self.container_dn = DN(
            self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(
            self.updater._template_str(
                'uid=tuser, cn=test, cn=accounts, $SUFFIX'))
Example #7
0
    def _ldap_update(self, filenames, *, basedir=paths.UPDATES_DIR):
        """Apply update ldif files

        Note: Additional substitution must be added to LDAPUpdate() to ensure
        that ipa-ldap-updater is able to handle all update files as well.

        :param filenames: list of file names
        :param basedir: base directory for files (default: UPDATES_DIR)
        :return: modified state
        """
        assert isinstance(filenames, (list, tuple))
        if basedir is not None:
            filenames = [os.path.join(basedir, fname) for fname in filenames]
        ld = LDAPUpdate(api=self.api)
        # assume that caller supplies files in correct order
        return ld.update(filenames, ordered=False)
Example #8
0
    def run(self):
        super(LDAPUpdater_NonUpgrade, self).run()
        options = self.options

        ld = LDAPUpdate(dm_password=self.dirman_password,
                        sub_dict={},
                        live_run=not options.test,
                        ldapi=options.ldapi,
                        plugins=options.plugins or self.run_plugins)

        if not self.files:
            self.files = ld.get_all_files(UPDATES_DIR)

        modified = ld.update(self.files, ordered=True)

        if modified and options.test:
            self.info('Update complete, changes to be made, test mode')
            return 2
Example #9
0
    def __recover_from_missing_maps(self, ldap):
        # https://fedorahosted.org/freeipa/ticket/5507
        # if all following DNs are missing, but 'NIS Server' container exists
        # we are experiencig bug and maps should be fixed

        if sysupgrade.get_upgrade_state('nis',
                                        'done_recover_from_missing_maps'):
            # this recover must be done only once, a user may deleted some
            # maps, we do not want to restore them again
            return

        logger.debug("Recovering from missing NIS maps bug")

        suffix = "cn=NIS Server,cn=plugins,cn=config"
        domain = self.api.env.domain
        missing_dn_list = [
            DN(nis_map.format(domain=domain, suffix=suffix)) for nis_map in [
                "nis-domain={domain}+nis-map=passwd.byname,{suffix}",
                "nis-domain={domain}+nis-map=passwd.byuid,{suffix}",
                "nis-domain={domain}+nis-map=group.byname,{suffix}",
                "nis-domain={domain}+nis-map=group.bygid,{suffix}",
                "nis-domain={domain}+nis-map=netid.byname,{suffix}",
                "nis-domain={domain}+nis-map=netgroup,{suffix}",
            ]
        ]

        for dn in missing_dn_list:
            try:
                ldap.get_entry(dn, attrs_list=['cn'])
            except errors.NotFound:
                pass
            else:
                # bug is not effective, at least one of 'possible missing'
                # maps was detected
                return

        sysupgrade.set_upgrade_state('nis', 'done_recover_from_missing_maps',
                                     True)

        # bug is effective run update to recreate missing maps
        ld = LDAPUpdate(sub_dict={}, ldapi=True)
        ld.update([paths.NIS_ULDIF])
Example #10
0
    def __recover_from_missing_maps(self, ldap):
        # https://fedorahosted.org/freeipa/ticket/5507
        # if all following DNs are missing, but 'NIS Server' container exists
        # we are experiencig bug and maps should be fixed

        if sysupgrade.get_upgrade_state('nis',
                                        'done_recover_from_missing_maps'):
            # this recover must be done only once, a user may deleted some
            # maps, we do not want to restore them again
            return

        logger.debug("Recovering from missing NIS maps bug")

        suffix = "cn=NIS Server,cn=plugins,cn=config"
        domain = self.api.env.domain
        missing_dn_list = [
            DN(nis_map.format(domain=domain, suffix=suffix)) for nis_map in [
                "nis-domain={domain}+nis-map=passwd.byname,{suffix}",
                "nis-domain={domain}+nis-map=passwd.byuid,{suffix}",
                "nis-domain={domain}+nis-map=group.byname,{suffix}",
                "nis-domain={domain}+nis-map=group.bygid,{suffix}",
                "nis-domain={domain}+nis-map=netid.byname,{suffix}",
                "nis-domain={domain}+nis-map=netgroup,{suffix}",
            ]
        ]

        for dn in missing_dn_list:
            try:
                ldap.get_entry(dn, attrs_list=['cn'])
            except errors.NotFound:
                pass
            else:
                # bug is not effective, at least one of 'possible missing'
                # maps was detected
                return

        sysupgrade.set_upgrade_state('nis', 'done_recover_from_missing_maps',
                                     True)

        # bug is effective run update to recreate missing maps
        ld = LDAPUpdate(sub_dict={}, ldapi=True)
        ld.update([paths.NIS_ULDIF])
Example #11
0
    def execute(self, **options):
        ldap = self.api.Backend.ldap2
        dn = DN(('cn', 'NIS Server'), ('cn', 'plugins'), ('cn', 'config'))
        try:
            ldap.get_entry(dn, attrs_list=['cn'])
        except errors.NotFound:
            # NIS is not configured on system, do not execute update
            logger.debug("Skipping NIS update, NIS Server is not configured")

            # container does not exist, bug #5507 is not effective
            sysupgrade.set_upgrade_state(
                'nis', 'done_recover_from_missing_maps', True)
        else:
            self.__recover_from_missing_maps(ldap)

            logger.debug("Executing NIS Server update")
            ld = LDAPUpdate(sub_dict={}, ldapi=True)
            ld.update([paths.NIS_UPDATE_ULDIF])

        return False, ()
Example #12
0
    def run(self):
        super(LDAPUpdater_NonUpgrade, self).run()
        options = self.options

        modified = False

        if options.schema_files:
            modified = schemaupdate.update_schema(options.schema_files, ldapi=True) or modified

        ld = LDAPUpdate(sub_dict={}, ldapi=True)

        if not self.files:
            self.files = ld.get_all_files(UPDATES_DIR)

        modified = ld.update(self.files) or modified

        if modified:
            self.log.info("Update complete")
        else:
            self.log.info("Update complete, no data were modified")
Example #13
0
    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if os.path.isfile(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise unittest.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={})
        self.ld = ipaldap.LDAPClient.from_hostname_secure(fqdn)
        self.ld.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
                            bind_password=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not os.path.isfile(os.path.join(self.testdir, "0_reset.update")):
            raise unittest.SkipTest("Unable to find test update files")

        self.container_dn = DN(
            self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(
            self.updater._template_str(
                'uid=tuser, cn=test, cn=accounts, $SUFFIX'))
Example #14
0
    def update(self, updatetype, dm_password, ldapi, live_run):
        """
        Execute all update plugins of type updatetype.
        """
        self.create_context(dm_password)
        kw = dict(live_run=live_run)
        result = []
        ld = LDAPUpdate(dm_password=dm_password, sub_dict={}, live_run=live_run, ldapi=ldapi)
        for update in self.order(updatetype):
            (restart, apply_now, res) = self.run(update.name, **kw)
            if restart:
                self.restart(dm_password, live_run)

            if apply_now:
                updates = {}
                for entry in res:
                    updates.update(entry)
                ld.update_from_dict(updates)
            elif res:
                result.extend(res)

        self.destroy_context()

        return result
Example #15
0
    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise nose.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={})
        self.ld = ipaldap.IPAdmin(fqdn)
        self.ld.do_simple_bind(bindpw=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not ipautil.file_exists(os.path.join(self.testdir,
                                                "0_reset.update")):
            raise nose.SkipTest("Unable to find test update files")

        self.container_dn = DN(self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX'))
Example #16
0
    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if os.path.isfile(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise unittest.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={})
        self.ld = ipaldap.LDAPClient.from_hostname_secure(fqdn)
        self.ld.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
                            bind_password=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not os.path.isfile(os.path.join(self.testdir,
                                                "0_reset.update")):
            raise unittest.SkipTest("Unable to find test update files")

        self.container_dn = DN(self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX'))
Example #17
0
class test_update(unittest.TestCase):
    """
    Test the LDAP updater.
    """

    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise nose.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={})
        self.ld = ipaldap.IPAdmin(fqdn)
        self.ld.do_simple_bind(bindpw=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not ipautil.file_exists(os.path.join(self.testdir,
                                                "0_reset.update")):
            raise nose.SkipTest("Unable to find test update files")

        self.container_dn = DN(self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX'))

    def tearDown(self):
        if self.ld:
            self.ld.unbind()

    def test_0_reset(self):
        """
        Reset the updater test data to a known initial state (test_0_reset)
        """
        try:
            modified = self.updater.update([os.path.join(self.testdir,
                                                         "0_reset.update")])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(
                self.container_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(
                self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])

    def test_1_add(self):
        """
        Test the updater with an add directive (test_1_add)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "1_add.update")])

        self.assertTrue(modified)

        entries = self.ld.get_entries(
            self.container_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'nsContainer'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['cn'], 'test')

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux', 'inetuser'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['loginshell'], paths.BASH)
        self.assertEqual(entry.single_value['sn'], 'User')
        self.assertEqual(entry.single_value['uid'], 'tuser')
        self.assertEqual(entry.single_value['cn'], 'Test User')


    def test_2_update(self):
        """
        Test the updater when adding an attribute to an existing entry (test_2_update)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "2_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User')

    def test_3_update(self):
        """
        Test the updater forcing an attribute to a given value (test_3_update)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "3_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User New')

    def test_4_update(self):
        """
        Test the updater adding a new value to a single-valued attribute (test_4_update)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "4_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User New2')

    def test_5_update(self):
        """
        Test the updater adding a new value to a multi-valued attribute (test_5_update)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "5_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User', 'Test User New']))

    def test_6_update(self):
        """
        Test the updater removing a value from a multi-valued attribute (test_6_update)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "6_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User']))

    def test_6_update_1(self):
        """
        Test the updater removing a non-existent value from a multi-valued attribute (test_6_update_1)
        """
        modified = self.updater.update([os.path.join(self.testdir,
                                                     "6_update.update")])
        self.assertFalse(modified)

        entries = self.ld.get_entries(
            self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User']))

    def test_7_cleanup(self):
        """
        Reset the test data to a known initial state (test_7_cleanup)
        """
        try:
            modified = self.updater.update([os.path.join(self.testdir,
                                                         "0_reset.update")])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(
                self.container_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(
                self.user_dn, self.ld.SCOPE_BASE, 'objectclass=*', ['*'])

    def test_8_badsyntax(self):
        """
        Test the updater with an unknown keyword (test_8_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            modified = self.updater.update(
                [os.path.join(self.testdir, "8_badsyntax.update")])

    def test_9_badsyntax(self):
        """
        Test the updater with an incomplete line (test_9_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            modified = self.updater.update(
                [os.path.join(self.testdir, "9_badsyntax.update")])
Example #18
0
class test_update(unittest.TestCase):
    """
    Test the LDAP updater.
    """

    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise nose.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={}, live_run=True)
        self.ld = ipaldap.IPAdmin(fqdn)
        self.ld.do_simple_bind(bindpw=self.dm_password)
        if ipautil.file_exists("0_reset.update"):
            self.testdir="./"
        elif ipautil.file_exists("tests/test_install/0_reset.update"):
            self.testdir= "./tests/test_install/"
        else:
            raise nose.SkipTest("Unable to find test update files")

        self.container_dn = DN(self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX'))

    def tearDown(self):
        if self.ld:
            self.ld.unbind()

    def test_0_reset(self):
        """
        Reset the updater test data to a known initial state (test_0_reset)
        """
        try:
            modified = self.updater.update([self.testdir + "0_reset.update"])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

    def test_1_add(self):
        """
        Test the updater with an add directive (test_1_add)
        """
        modified = self.updater.update([self.testdir + "1_add.update"])

        self.assertTrue(modified)

        entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.getValues('objectclass')
        for item in ('top', 'nsContainer'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.getValue('cn'), 'test')

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.getValues('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux', 'inetuser'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.getValue('loginshell'), '/bin/bash')
        self.assertEqual(entry.getValue('sn'), 'User')
        self.assertEqual(entry.getValue('uid'), 'tuser')
        self.assertEqual(entry.getValue('cn'), 'Test User')


    def test_2_update(self):
        """
        Test the updater when adding an attribute to an existing entry (test_2_update)
        """
        modified = self.updater.update([self.testdir + "2_update.update"])
        self.assertTrue(modified)

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.getValue('gecos'), 'Test User')

    def test_3_update(self):
        """
        Test the updater forcing an attribute to a given value (test_3_update)
        """
        modified = self.updater.update([self.testdir + "3_update.update"])
        self.assertTrue(modified)

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.getValue('gecos'), 'Test User New')

    def test_4_update(self):
        """
        Test the updater adding a new value to a single-valued attribute (test_4_update)
        """
        modified = self.updater.update([self.testdir + "4_update.update"])
        self.assertTrue(modified)

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.getValue('gecos'), 'Test User New2')

    def test_5_update(self):
        """
        Test the updater adding a new value to a multi-valued attribute (test_5_update)
        """
        modified = self.updater.update([self.testdir + "5_update.update"])
        self.assertTrue(modified)

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.getValues('cn')), sorted(['Test User', 'Test User New']))

    def test_6_update(self):
        """
        Test the updater removing a value from a multi-valued attribute (test_6_update)
        """
        modified = self.updater.update([self.testdir + "6_update.update"])
        self.assertTrue(modified)

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.getValues('cn')), sorted(['Test User']))

    def test_6_update_1(self):
        """
        Test the updater removing a non-existent value from a multi-valued attribute (test_6_update_1)
        """
        modified = self.updater.update([self.testdir + "6_update.update"])
        self.assertFalse(modified)

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.getValues('cn')), sorted(['Test User']))

    def test_7_cleanup(self):
        """
        Reset the test data to a known initial state (test_7_cleanup)
        """
        try:
            modified = self.updater.update([self.testdir + "0_reset.update"])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

    def test_8_badsyntax(self):
        """
        Test the updater with an unknown keyword (test_8_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            modified = self.updater.update([self.testdir + "8_badsyntax.update"])

    def test_9_badsyntax(self):
        """
        Test the updater with an incomplete line (test_9_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            modified = self.updater.update([self.testdir + "9_badsyntax.update"])

    def test_from_dict(self):
        """
        Test updating from a dict.

        This replicates what was done in test 1.
        """

        # First make sure we're clean
        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])


        update = {
            self.container_dn:
                {'dn': self.container_dn,
                 'updates': ['add:objectClass: top',
                             'add:objectClass: nsContainer',
                             'add:cn: test'
                            ],
                },
            self.user_dn:
                {'dn': self.user_dn,
                 'updates': ['add:objectclass: top',
                             'add:objectclass: person',
                             'add:objectclass: posixaccount',
                             'add:objectclass: krbprincipalaux',
                             'add:objectclass: inetuser',
                             'add:homedirectory: /home/tuser',
                             'add:loginshell: /bin/bash',
                             'add:sn: User',
                             'add:uid: tuser',
                             'add:uidnumber: 999',
                             'add:gidnumber: 999',
                             'add:cn: Test User',
                            ],
                },
        }

        modified = self.updater.update_from_dict(update)
        self.assertTrue(modified)

        entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.getValues('objectclass')
        for item in ('top', 'nsContainer'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.getValue('cn'), 'test')

        entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.getValues('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux', 'inetuser'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.getValue('loginshell'), '/bin/bash')
        self.assertEqual(entry.getValue('sn'), 'User')
        self.assertEqual(entry.getValue('uid'), 'tuser')
        self.assertEqual(entry.getValue('cn'), 'Test User')

        # Now delete

        update = {
            self.container_dn:
                {'dn': self.container_dn,
                 'deleteentry': None,
                },
            self.user_dn:
                {'dn': self.user_dn,
                 'deleteentry': 'deleteentry: reset: nada',
                },
        }

        modified = self.updater.update_from_dict(update)
        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
Example #19
0
class test_update(unittest.TestCase):
    """
    Test the LDAP updater.
    """
    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if os.path.isfile(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise nose.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={})
        ldap_uri = ipaldap.get_ldap_uri(fqdn)
        self.ld = ipaldap.LDAPClient(ldap_uri)
        self.ld.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
                            bind_password=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not os.path.isfile(os.path.join(self.testdir, "0_reset.update")):
            raise nose.SkipTest("Unable to find test update files")

        self.container_dn = DN(
            self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(
            self.updater._template_str(
                'uid=tuser, cn=test, cn=accounts, $SUFFIX'))

    def tearDown(self):
        if self.ld:
            self.ld.unbind()

    def test_0_reset(self):
        """
        Reset the updater test data to a known initial state (test_0_reset)
        """
        try:
            modified = self.updater.update(
                [os.path.join(self.testdir, "0_reset.update")])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

    def test_1_add(self):
        """
        Test the updater with an add directive (test_1_add)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "1_add.update")])

        self.assertTrue(modified)

        entries = self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'nsContainer'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['cn'], 'test')

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux',
                     'inetuser'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['loginshell'], paths.BASH)
        self.assertEqual(entry.single_value['sn'], 'User')
        self.assertEqual(entry.single_value['uid'], 'tuser')
        self.assertEqual(entry.single_value['cn'], 'Test User')

    def test_2_update(self):
        """
        Test the updater when adding an attribute to an existing entry (test_2_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "2_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User')

    def test_3_update(self):
        """
        Test the updater forcing an attribute to a given value (test_3_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "3_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User New')

    def test_4_update(self):
        """
        Test the updater adding a new value to a single-valued attribute (test_4_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "4_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User New2')

    def test_5_update(self):
        """
        Test the updater adding a new value to a multi-valued attribute (test_5_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "5_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')),
                         sorted(['Test User', 'Test User New']))

    def test_6_update(self):
        """
        Test the updater removing a value from a multi-valued attribute (test_6_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "6_update.update")])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User']))

    def test_6_update_1(self):
        """
        Test the updater removing a non-existent value from a multi-valued attribute (test_6_update_1)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "6_update.update")])
        self.assertFalse(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User']))

    def test_7_cleanup(self):
        """
        Reset the test data to a known initial state (test_7_cleanup)
        """
        try:
            modified = self.updater.update(
                [os.path.join(self.testdir, "0_reset.update")])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

        with self.assertRaises(errors.NotFound):
            self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

    def test_8_badsyntax(self):
        """
        Test the updater with an unknown keyword (test_8_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            self.updater.update(
                [os.path.join(self.testdir, "8_badsyntax.update")])

    def test_9_badsyntax(self):
        """
        Test the updater with an incomplete line (test_9_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            self.updater.update(
                [os.path.join(self.testdir, "9_badsyntax.update")])
Example #20
0
class TestUpdate:
    """
    Test the LDAP updater.
    """
    @pytest.fixture(autouse=True)
    def update_setup(self, request):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if os.path.isfile(pwfile):
            with open(pwfile, "r") as fp:
                self.dm_password = fp.read().rstrip()
        else:
            pytest.skip("No directory manager password")
        self.updater = LDAPUpdate()
        self.ld = ipaldap.LDAPClient.from_hostname_secure(fqdn)
        self.ld.simple_bind(bind_dn=ipaldap.DIRMAN_DN,
                            bind_password=self.dm_password)
        self.testdir = os.path.abspath(os.path.dirname(__file__))
        if not os.path.isfile(os.path.join(self.testdir, "0_reset.update")):
            pytest.skip("Unable to find test update files")

        self.container_dn = DN(
            self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(
            self.updater._template_str(
                'uid=tuser, cn=test, cn=accounts, $SUFFIX'))

        def fin():
            if self.ld:
                self.ld.unbind()

        request.addfinalizer(fin)

    def test_0_reset(self):
        """
        Reset the updater test data to a known initial state (test_0_reset)
        """
        try:
            modified = self.updater.update(
                [os.path.join(self.testdir, "0_reset.update")])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        assert modified

        with pytest.raises(errors.NotFound):
            self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

        with pytest.raises(errors.NotFound):
            self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

    def test_1_add(self):
        """
        Test the updater with an add directive (test_1_add)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "1_add.update")])

        assert modified

        entries = self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'nsContainer'):
            assert item in objectclasses

        assert entry.single_value['cn'] == 'test'

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux',
                     'inetuser'):
            assert item in objectclasses

        actual = entry.single_value['loginshell']
        assert actual == platformconstants.DEFAULT_ADMIN_SHELL
        assert entry.single_value['sn'] == 'User'
        assert entry.single_value['uid'] == 'tuser'
        assert entry.single_value['cn'] == 'Test User'

    def test_2_update(self):
        """
        Test the updater when adding an attribute to an existing entry (test_2_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "2_update.update")])
        assert modified

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]
        assert entry.single_value['gecos'] == 'Test User'

    def test_3_update(self):
        """
        Test the updater forcing an attribute to a given value (test_3_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "3_update.update")])
        assert modified

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]
        assert entry.single_value['gecos'] == 'Test User New'

    def test_4_update(self):
        """
        Test the updater adding a new value to a single-valued attribute (test_4_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "4_update.update")])
        assert modified

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]
        assert entry.single_value['gecos'] == 'Test User New2'

    def test_5_update(self):
        """
        Test the updater adding a new value to a multi-valued attribute (test_5_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "5_update.update")])
        assert modified

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]
        actual = sorted(entry.get('cn'))
        expected = sorted(['Test User', 'Test User New'])
        assert actual == expected

    def test_6_update(self):
        """
        Test the updater removing a value from a multi-valued attribute (test_6_update)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "6_update.update")])
        assert modified

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]
        assert sorted(entry.get('cn')) == sorted(['Test User'])

    def test_6_update_1(self):
        """
        Test the updater removing a non-existent value from a multi-valued attribute (test_6_update_1)
        """
        modified = self.updater.update(
            [os.path.join(self.testdir, "6_update.update")])
        assert not modified

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        assert len(entries) == 1
        entry = entries[0]
        assert sorted(entry.get('cn')) == sorted(['Test User'])

    def test_7_cleanup(self):
        """
        Reset the test data to a known initial state (test_7_cleanup)
        """
        try:
            modified = self.updater.update(
                [os.path.join(self.testdir, "0_reset.update")])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        assert modified

        with pytest.raises(errors.NotFound):
            self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

        with pytest.raises(errors.NotFound):
            self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                'objectclass=*', ['*'])

    def test_8_badsyntax(self):
        """
        Test the updater with an unknown keyword (test_8_badsyntax)
        """
        with pytest.raises(BadSyntax):
            self.updater.update(
                [os.path.join(self.testdir, "8_badsyntax.update")])

    def test_9_badsyntax(self):
        """
        Test the updater with an incomplete line (test_9_badsyntax)
        """
        with pytest.raises(BadSyntax):
            self.updater.update(
                [os.path.join(self.testdir, "9_badsyntax.update")])
Example #21
0
class test_update(unittest.TestCase):
    """
    Test the LDAP updater.
    """
    def setUp(self):
        fqdn = installutils.get_fqdn()
        pwfile = api.env.dot_ipa + os.sep + ".dmpw"
        if ipautil.file_exists(pwfile):
            fp = open(pwfile, "r")
            self.dm_password = fp.read().rstrip()
            fp.close()
        else:
            raise nose.SkipTest("No directory manager password")
        self.updater = LDAPUpdate(dm_password=self.dm_password, sub_dict={})
        self.ld = ipaldap.IPAdmin(fqdn)
        self.ld.do_simple_bind(bindpw=self.dm_password)
        if ipautil.file_exists("0_reset.update"):
            self.testdir = "./"
        elif ipautil.file_exists("ipatests/test_install/0_reset.update"):
            self.testdir = "./ipatests/test_install/"
        else:
            raise nose.SkipTest("Unable to find test update files")

        self.container_dn = DN(
            self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
        self.user_dn = DN(
            self.updater._template_str(
                'uid=tuser, cn=test, cn=accounts, $SUFFIX'))

    def tearDown(self):
        if self.ld:
            self.ld.unbind()

    def test_0_reset(self):
        """
        Reset the updater test data to a known initial state (test_0_reset)
        """
        try:
            modified = self.updater.update([self.testdir + "0_reset.update"])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.container_dn,
                                          self.ld.SCOPE_BASE, 'objectclass=*',
                                          ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                          'objectclass=*', ['*'])

    def test_1_add(self):
        """
        Test the updater with an add directive (test_1_add)
        """
        modified = self.updater.update([self.testdir + "1_add.update"])

        self.assertTrue(modified)

        entries = self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'nsContainer'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['cn'], 'test')

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux',
                     'inetuser'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['loginshell'], paths.BASH)
        self.assertEqual(entry.single_value['sn'], 'User')
        self.assertEqual(entry.single_value['uid'], 'tuser')
        self.assertEqual(entry.single_value['cn'], 'Test User')

    def test_2_update(self):
        """
        Test the updater when adding an attribute to an existing entry (test_2_update)
        """
        modified = self.updater.update([self.testdir + "2_update.update"])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User')

    def test_3_update(self):
        """
        Test the updater forcing an attribute to a given value (test_3_update)
        """
        modified = self.updater.update([self.testdir + "3_update.update"])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User New')

    def test_4_update(self):
        """
        Test the updater adding a new value to a single-valued attribute (test_4_update)
        """
        modified = self.updater.update([self.testdir + "4_update.update"])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(entry.single_value['gecos'], 'Test User New2')

    def test_5_update(self):
        """
        Test the updater adding a new value to a multi-valued attribute (test_5_update)
        """
        modified = self.updater.update([self.testdir + "5_update.update"])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')),
                         sorted(['Test User', 'Test User New']))

    def test_6_update(self):
        """
        Test the updater removing a value from a multi-valued attribute (test_6_update)
        """
        modified = self.updater.update([self.testdir + "6_update.update"])
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User']))

    def test_6_update_1(self):
        """
        Test the updater removing a non-existent value from a multi-valued attribute (test_6_update_1)
        """
        modified = self.updater.update([self.testdir + "6_update.update"])
        self.assertFalse(modified)

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]
        self.assertEqual(sorted(entry.get('cn')), sorted(['Test User']))

    def test_7_cleanup(self):
        """
        Reset the test data to a known initial state (test_7_cleanup)
        """
        try:
            modified = self.updater.update([self.testdir + "0_reset.update"])
        except errors.NotFound:
            # Just means the entry doesn't exist yet
            modified = True

        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.container_dn,
                                          self.ld.SCOPE_BASE, 'objectclass=*',
                                          ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                          'objectclass=*', ['*'])

    def test_8_badsyntax(self):
        """
        Test the updater with an unknown keyword (test_8_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            modified = self.updater.update(
                [self.testdir + "8_badsyntax.update"])

    def test_9_badsyntax(self):
        """
        Test the updater with an incomplete line (test_9_badsyntax)
        """
        with self.assertRaises(BadSyntax):
            modified = self.updater.update(
                [self.testdir + "9_badsyntax.update"])

    def test_from_dict(self):
        """
        Test updating from a dict.

        This replicates what was done in test 1.
        """

        # First make sure we're clean
        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.container_dn,
                                          self.ld.SCOPE_BASE, 'objectclass=*',
                                          ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                          'objectclass=*', ['*'])

        update = {
            self.container_dn: {
                'dn':
                self.container_dn,
                'updates': [
                    'add:objectClass: top', 'add:objectClass: nsContainer',
                    'add:cn: test'
                ],
            },
            self.user_dn: {
                'dn':
                self.user_dn,
                'updates': [
                    'add:objectclass: top',
                    'add:objectclass: person',
                    'add:objectclass: posixaccount',
                    'add:objectclass: krbprincipalaux',
                    'add:objectclass: inetuser',
                    'add:homedirectory: /home/tuser',
                    'add:loginshell: /bin/bash',
                    'add:sn: User',
                    'add:uid: tuser',
                    'add:uidnumber: 999',
                    'add:gidnumber: 999',
                    'add:cn: Test User',
                ],
            },
        }

        modified = self.updater.update_from_dict(update)
        self.assertTrue(modified)

        entries = self.ld.get_entries(self.container_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'nsContainer'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['cn'], 'test')

        entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                      'objectclass=*', ['*'])
        self.assertEqual(len(entries), 1)
        entry = entries[0]

        objectclasses = entry.get('objectclass')
        for item in ('top', 'person', 'posixaccount', 'krbprincipalaux',
                     'inetuser'):
            self.assertTrue(item in objectclasses)

        self.assertEqual(entry.single_value['loginshell'], paths.BASH)
        self.assertEqual(entry.single_value['sn'], 'User')
        self.assertEqual(entry.single_value['uid'], 'tuser')
        self.assertEqual(entry.single_value['cn'], 'Test User')

        # Now delete

        update = {
            self.container_dn: {
                'dn': self.container_dn,
                'deleteentry': None,
            },
            self.user_dn: {
                'dn': self.user_dn,
                'deleteentry': 'deleteentry: reset: nada',
            },
        }

        modified = self.updater.update_from_dict(update)
        self.assertTrue(modified)

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.container_dn,
                                          self.ld.SCOPE_BASE, 'objectclass=*',
                                          ['*'])

        with self.assertRaises(errors.NotFound):
            entries = self.ld.get_entries(self.user_dn, self.ld.SCOPE_BASE,
                                          'objectclass=*', ['*'])