On 05/28/2013 04:49 PM, Ana Krivokapic wrote: > Hello, > > This patch addresses https://fedorahosted.org/freeipa/ticket/3634 > > > > _______________________________________________ > Freeipa-devel mailing list > Freeipa-devel@redhat.com > https://www.redhat.com/mailman/listinfo/freeipa-devel
This updated patch applies on top of tbabej's patches 0053-0055. As suggested by Tomás( (https://www.redhat.com/archives/freeipa-devel/2013-May/msg00352.html), I refactored support of "mock" LDAP objects to tests/util, and modified test_range_plugin and test_cli to use it. -- Regards, Ana Krivokapic Associate Software Engineer FreeIPA team Red Hat Inc.
From 9b18dcd752940df00e7bce429c9eb572434da1c6 Mon Sep 17 00:00:00 2001 From: Ana Krivokapic <akriv...@redhat.com> Date: Tue, 28 May 2013 16:42:03 +0200 Subject: [PATCH] Require rid-base and secondary-rid-base options in idrange-add when trust exists https://fedorahosted.org/freeipa/ticket/3634 --- ipalib/plugins/idrange.py | 34 +++++++++++++- tests/test_cmdline/test_cli.py | 68 +++++++++++++++++++++++++++ tests/test_xmlrpc/test_range_plugin.py | 85 ++++++++++------------------------ tests/util.py | 37 ++++++++++++--- 4 files changed, 156 insertions(+), 68 deletions(-) diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py index 73628795aaa069b436371be3d9c989e97916f1f6..0cfa7c28516f6920e277d19a993d51339cf85756 100644 --- a/ipalib/plugins/idrange.py +++ b/ipalib/plugins/idrange.py @@ -340,7 +340,7 @@ class idrange_add(LDAPCreate): may be given for a new ID range for the local domain while - --rid-bas + --rid-base --dom-sid must be given to add a new range for a trusted AD domain. @@ -365,6 +365,9 @@ def interactive_prompt_callback(self, kw): Also ensure that secondary-rid-base is prompted for when rid-base is specified and vice versa, in case that dom-sid was not specified. + + Interactive mode should prompt for rid-base and secondary-rid-base + if a trust is established. """ # dom-sid can be specified using dom-sid or dom-name options @@ -394,6 +397,21 @@ def interactive_prompt_callback(self, kw): value = self.prompt_param(self.params['ipabaserid']) kw.update(dict(ipabaserid=value)) + trust_exists = api.Command['trust_find']()['count'] + + if trust_exists: + + rid_base = kw.get('ipabaserid', None) + secondary_rid_base = kw.get('ipasecondarybaserid', None) + + if rid_base is None: + value = self.prompt_param(self.params['ipabaserid']) + kw.update(dict(ipabaserid=value)) + + if secondary_rid_base is None: + value = self.prompt_param(self.params['ipasecondarybaserid']) + kw.update(dict(ipasecondarybaserid=value)) + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): assert isinstance(dn, DN) @@ -451,6 +469,20 @@ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): error=_("Primary RID range and secondary RID range" " cannot overlap")) + # If a trust is established, base rid and secondary base rid + # must be specified for local id range + trust_exists = api.Command['trust_find']()['count'] + + if trust_exists and not ( + is_set('ipabaserid') and is_set('ipasecondarybaserid')): + raise errors.ValidationError( + name='ID Range setup', + error=_('You must specify both rid-base and ' + 'secondary-rid-base options, because a trust is ' + 'established.' + ) + ) + entry_attrs['objectclass'].append('ipadomainidrange') return dn diff --git a/tests/test_cmdline/test_cli.py b/tests/test_cmdline/test_cli.py index bd1281e1d682b055ede9685a10a9cec91a3c76fd..d01d9455b8d851a03fabd824f2b84224e918bdde 100644 --- a/tests/test_cmdline/test_cli.py +++ b/tests/test_cmdline/test_cli.py @@ -6,6 +6,7 @@ import nose from tests import util +from tests.test_xmlrpc.test_range_plugin import testtrust_dn, testtrust_add from ipalib import api, errors from ipapython.version import API_VERSION @@ -325,3 +326,70 @@ def test_dnszone_add(self): force=False, version=API_VERSION ) + + def test_idrange_add(self): + """ + Test idrange-add with interative prompt + """ + def test_with_interactive_input(): + with self.fake_stdin('5\n500000\n'): + self.check_command( + 'idrange_add range1 --base-id=1 --range-size=1', + 'idrange_add', + cn=u'range1', + ipabaseid=u'1', + ipaidrangesize=u'1', + ipabaserid=5, + ipasecondarybaserid=500000, + all=False, + raw=False, + version=API_VERSION + ) + + def test_with_command_line_options(): + self.check_command( + 'idrange_add range1 --base-id=1 --range-size=1 ' + '--rid-base=5 --secondary-rid-base=500000', + 'idrange_add', + cn=u'range1', + ipabaseid=u'1', + ipaidrangesize=u'1', + ipabaserid=u'5', + ipasecondarybaserid=u'500000', + all=False, + raw=False, + version=API_VERSION + ) + + def test_without_options(): + self.check_command( + 'idrange_add range1 --base-id=1 --range-size=1', + 'idrange_add', + cn=u'range1', + ipabaseid=u'1', + ipaidrangesize=u'1', + all=False, + raw=False, + version=API_VERSION + ) + + trust_exists = api.Command['trust_find']()['count'] + mockldap = None + + if not trust_exists: + # Trust not established - no need to pass rid-base + # and secondary-rid-base + test_without_options() + + # Create a mock trust to test against + mockldap = util.MockLDAP() + mockldap.add_entry(testtrust_dn, testtrust_add) + + # Pass rid-base and secondary-rid-base interactively + test_with_interactive_input() + + # Pass rid-base and secondary-rid-base on the command-line + test_with_command_line_options() + + if not trust_exists: + mockldap.del_entry(testtrust_dn) diff --git a/tests/test_xmlrpc/test_range_plugin.py b/tests/test_xmlrpc/test_range_plugin.py index ce70433112b3216304356b520026d79be66543cf..e21b64f160d5fcb62be8e525ec0d340fd49998bb 100644 --- a/tests/test_xmlrpc/test_range_plugin.py +++ b/tests/test_xmlrpc/test_range_plugin.py @@ -21,13 +21,12 @@ Test the `ipalib/plugins/idrange.py` module, and XML-RPC in general. """ -from ipalib import api, errors, _ -from tests.util import assert_equal, Fuzzy -from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid +from ipalib import api, errors +from xmlrpc_test import Declarative, fuzzy_uuid from tests.test_xmlrpc import objectclasses -from ipapython.dn import * +from tests.util import MockLDAP +from ipapython.dn import DN -import ldap, ldap.sasl, ldap.modlist testrange1 = u'testrange1' testrange1_base_id = 900000 @@ -75,6 +74,7 @@ testrange8_base_id = 700 testrange8_size = 50 testrange8_base_rid = 700 +testrange8_secondary_base_rid = 800 testrange9 = u'testrange9' testrange9_base_id = 800 @@ -129,59 +129,26 @@ class test_range(Declarative): - def __init__(self): super(test_range, self).__init__() - self.connection = None @classmethod - def connect_ldap(self): - self.connection = ldap.initialize('ldap://{host}' - .format(host=api.env.host)) - - auth = ldap.sasl.gssapi("") - self.connection.sasl_interactive_bind_s('', auth) - - @classmethod - def add_entry(self, dn, mods): - ldif = ldap.modlist.addModlist(mods) - self.connection.add_s(dn, ldif) + def setUpClass(cls): + super(test_range, cls).setUpClass() + cls.tearDownClass() + cls.mockldap = MockLDAP() + cls.mockldap.add_entry(testrange9_dn, testrange9_add) + cls.mockldap.add_entry(testrange10_dn, testrange10_add) + cls.mockldap.add_entry(testtrust_dn, testtrust_add) + cls.mockldap.unbind() @classmethod - def setUpClass(self): - super(test_range, self).setUpClass() - - self.tearDownClass() - - try: - self.connect_ldap() - - self.add_entry(testrange9_dn, testrange9_add) - self.add_entry(testrange10_dn, testrange10_add) - self.add_entry(testtrust_dn, testtrust_add) - - except ldap.ALREADY_EXISTS: - pass - - finally: - if self.connection is not None: - self.connection.unbind_s() - - @classmethod - def tearDownClass(self): - - try: - self.connect_ldap() - self.connection.delete_s(testrange9_dn) - self.connection.delete_s(testrange10_dn) - self.connection.delete_s(testtrust_dn) - - except ldap.NO_SUCH_OBJECT: - pass - - finally: - if self.connection is not None: - self.connection.unbind_s() + def tearDownClass(cls): + cls.mockldap = MockLDAP() + cls.mockldap.del_entry(testrange9_dn) + cls.mockldap.del_entry(testrange10_dn) + cls.mockldap.del_entry(testtrust_dn) + cls.mockldap.unbind() cleanup_commands = [ ('idrange_del', [testrange1, testrange2, testrange3, testrange4, @@ -480,7 +447,9 @@ def tearDownClass(self): desc='Create ID range %r' % (testrange8), command=('idrange_add', [testrange8], dict(ipabaseid=testrange8_base_id, - ipaidrangesize=testrange8_size)), + ipaidrangesize=testrange8_size, + ipabaserid=testrange8_base_rid, + ipasecondarybaserid=testrange8_secondary_base_rid)), expected=dict( result=dict( dn=DN(('cn',testrange8),('cn','ranges'),('cn','etc'), @@ -490,6 +459,8 @@ def tearDownClass(self): ipabaseid=[unicode(testrange8_base_id)], ipaidrangesize=[unicode(testrange8_size)], iparangetype=[u'local domain range'], + ipabaserid=[unicode(testrange8_base_rid)], + ipasecondarybaserid=[unicode(testrange8_secondary_base_rid)] ), value=testrange8, summary=u'Added ID range "%s"' % (testrange8), @@ -497,14 +468,6 @@ def tearDownClass(self): ), dict( - desc='Try to modify ID range %r so it has only primary rid range set' % (testrange8), - command=('idrange_mod', [testrange8], - dict(ipabaserid=testrange8_base_rid)), - expected=errors.ValidationError( - name='ID Range setup', error='Options secondary-rid-base and rid-base must be used together'), - ), - - dict( desc='Delete ID range %r' % testrange8, command=('idrange_del', [testrange8], {}), expected=dict( diff --git a/tests/util.py b/tests/util.py index 117d2c834563dcdc09799d4ce4baa1349390e111..a3c875fbb9f14feee225a72db41e10e6025d77f9 100644 --- a/tests/util.py +++ b/tests/util.py @@ -24,6 +24,9 @@ import inspect import os from os import path +import ldap +import ldap.sasl +import ldap.modlist import tempfile import shutil import re @@ -32,6 +35,7 @@ from ipalib.request import context from ipapython.dn import DN + class TempDir(object): def __init__(self): self.__path = tempfile.mkdtemp(prefix='ipa.tests.') @@ -451,12 +455,6 @@ def tearDown(self): context.__dict__.clear() - - - - - - def check_TypeError(value, type_, name, callback, *args, **kw): """ Tests a standard TypeError raised with `errors.raise_TypeError`. @@ -635,3 +633,30 @@ def __process(self, name_, args_, kw_): def _calledall(self): return self.__i == len(self.__calls) + + +class MockLDAP(object): + def __init__(self): + self.connection = ldap.initialize( + 'ldap://{host}'.format(host=ipalib.api.env.host) + ) + + auth = ldap.sasl.gssapi("") + self.connection.sasl_interactive_bind_s('', auth) + + def add_entry(self, dn, mods): + try: + ldif = ldap.modlist.addModlist(mods) + self.connection.add_s(dn, ldif) + except ldap.ALREADY_EXISTS: + pass + + def del_entry(self, dn): + try: + self.connection.delete_s(dn) + except ldap.NO_SUCH_OBJECT: + pass + + def unbind(self): + if self.connection is not None: + self.connection.unbind_s() -- 1.8.1.4
_______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel