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

Reply via email to