Repository: F5Networks/f5-common-python

Issue:
Add LTM authentication API to the SDK 
I would like to explore the feasibility of adding LTM authentication API into SDK  given the planned changes to that part of LTM.

Discussion:

Patch:
diff --git a/f5/bigip/tm/ltm/__init__.py b/f5/bigip/tm/ltm/__init__.py
index 240a424..3307a7a 100644
--- a/f5/bigip/tm/ltm/__init__.py
+++ b/f5/bigip/tm/ltm/__init__.py
@@ -29,6 +29,7 @@ REST Kind
 
 
 from f5.bigip.resource import OrganizingCollection
+from f5.bigip.tm.ltm.auth import Auth
 from f5.bigip.tm.ltm.data_group import Data_Group
 from f5.bigip.tm.ltm.ifile import Ifiles
 from f5.bigip.tm.ltm.monitor import Monitor
@@ -52,6 +53,7 @@ class Ltm(OrganizingCollection):
     def __init__(self, tm):
         super(Ltm, self).__init__(tm)
         self._meta_data['allowed_lazy_attributes'] = [
+            Auth,
             Data_Group,
             Ifiles,
             Monitor,
diff --git a/f5/bigip/tm/ltm/auth.py b/f5/bigip/tm/ltm/auth.py
new file mode 100644
index 0000000..b764185
--- /dev/null
+++ b/f5/bigip/tm/ltm/auth.py
@@ -0,0 +1,259 @@
+# coding=utf-8
+#
+#  Copyright 2014-2016 F5 Networks Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""BIG-IP® LTM auth submodule.
+
+REST URI
+    ``http://localhost/mgmt/tm/ltm/auth/``
+
+GUI Path
+    ``Local Traffic --> Profiles --> Authentication``
+
+REST Kind
+    ``tm:ltm:auth:*``
+"""
+from f5.bigip.mixins import UnsupportedMethod
+from f5.bigip.resource import Collection
+from f5.bigip.resource import OrganizingCollection
+from f5.bigip.resource import Resource
+
+
+class Auth(OrganizingCollection):
+    """BIG-IP® LTM Authentication organizing collection."""
+    def __init__(self, ltm):
+        super(Auth, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [
+            Crldp_Servers,
+            Kerberos_Delegations,
+            Ldaps,
+            Ocsp_Responders,
+            Profiles,
+            Radius_s,
+            Radius_Servers,
+            Ssl_Cc_Ldaps,
+            Ssl_Crldps,
+            Ssl_Ocsps,
+            Tacacs_s
+        ]
+
+
+class Crldp_Servers(Collection):
+    """BIG-IP® LTM Auth Crldp Server collection"""
+    def __init__(self, ltm):
+        super(Crldp_Servers, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Crldp_Server]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:crldp-server:crldp-serverstate': Crldp_Server}
+
+
+class Crldp_Server(Resource):
+    def __init__(self, crldp_servers):
+        """BIG-IP® LTM Auth Crldp Server resource"""
+        super(Crldp_Server, self).__init__(crldp_servers)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:crldp-server:crldp-serverstate'
+        self._meta_data['required_creation_parameters'].update(('host',))
+
+
+class Kerberos_Delegations(Collection):
+    """BIG-IP® LTM Auth Kerberos Delegation collection"""
+    def __init__(self, ltm):
+        super(Kerberos_Delegations, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Kerberos_Delegation]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:kerberos-delegation:kerberos-delegationstate':
+                Kerberos_Delegation}
+
+
+class Kerberos_Delegation(Resource):
+    """BIG-IP® LTM Auth Kerberos Delegation resource"""
+    def __init__(self, kerberos_delegations):
+        super(Kerberos_Delegation, self).__init__(kerberos_delegations)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:kerberos-delegation:kerberos-delegationstate'
+        self._meta_data['required_creation_parameters'].update(
+            ('serverPrincipal', 'clientPrincipal',))
+
+
+class Ldaps(Collection):
+    """BIG-IP® LTM Auth Ldap collection"""
+    def __init__(self, ltm):
+        super(Ldaps, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Ldap]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:ldap:ldapstate': Ldap}
+
+
+class Ldap(Resource):
+    """BIG-IP® LTM Auth Ldap resource"""
+    def __init__(self, ldaps):
+        super(Ldap, self).__init__(ldaps)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:ldap:ldapstate'
+        self._meta_data['required_creation_parameters'].update(('servers',))
+
+
+class Ocsp_Responders(Collection):
+    """BIG-IP® LTM Auth Ocsp Responder collection"""
+    def __init__(self, ltm):
+        super(Ocsp_Responders, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Ocsp_Responder]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:ocsp-responder:ocsp-responderstate': Ocsp_Responder}
+
+
+class Ocsp_Responder(Resource):
+    """BIG-IP® LTM Auth Ocsp Responder resource"""
+    def __init__(self, ocsp_responders):
+        super(Ocsp_Responder, self).__init__(ocsp_responders)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:ocsp-responder:ocsp-responderstate'
+
+
+class Profiles(Collection):
+    """BIG-IP® LTM Auth Profile collection"""
+    def __init__(self, ltm):
+        super(Profiles, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Profile]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:profile:profilestate': Profile}
+
+
+class Profile(Resource):
+    """BIG-IP® LTM Auth Profile resource"""
+    def __init__(self, profiles):
+        super(Profile, self).__init__(profiles)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:profile:profilestate'
+        self._meta_data['required_creation_parameters'].update(
+            ('defaultsFrom', 'configuration',))
+
+    def update(self, **kwargs):
+        '''Update is not supported for LTM Auth Profiles
+
+        :raises: UnsupportedOperation
+        '''
+        raise UnsupportedMethod(
+            "%s does not support the modify method" % self.__class__.__name__
+        )
+
+
+class Radius_s(Collection):
+    """BIG-IP® LTM Auth Radius collection"""
+    def __init__(self, ltm):
+        super(Radius_s, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Radius]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:radius:radiusstate': Radius}
+
+
+class Radius(Resource):
+    """BIG-IP® LTM Auth Radius resource"""
+    def __init__(self, radius_s):
+        super(Radius, self).__init__(radius_s)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:radius:radiusstate'
+
+
+class Radius_Servers(Collection):
+    """BIG-IP® LTM Auth Radius Server collection"""
+    def __init__(self, ltm):
+        super(Radius_Servers, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Radius_Server]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:radius-server:radius-serverstate': Radius_Server}
+
+
+class Radius_Server(Resource):
+    """BIG-IP® LTM Auth Radius Server resource"""
+    def __init__(self, radius_server_s):
+        super(Radius_Server, self).__init__(radius_server_s)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:radius-server:radius-serverstate'
+        self._meta_data['required_creation_parameters'].update(
+            ('secret', 'server',))
+
+
+class Ssl_Cc_Ldaps(Collection):
+    """BIG-IP® LTM Auth SSL CC LDAP collection"""
+    def __init__(self, ltm):
+        super(Ssl_Cc_Ldaps, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Ssl_Cc_Ldap]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:ssl-cc-ldap:ssl-cc-ldapstate': Ssl_Cc_Ldap}
+
+
+class Ssl_Cc_Ldap(Resource):
+    """BIG-IP® LTM Auth SSL CC LDAP resource"""
+    def __init__(self, ssl_cc_ldaps):
+        super(Ssl_Cc_Ldap, self).__init__(ssl_cc_ldaps)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:ssl-cc-ldap:ssl-cc-ldapstate'
+        self._meta_data['required_creation_parameters'].update(
+            ('servers', 'userKey',))
+
+
+class Ssl_Crldps(Collection):
+    """BIG-IP® LTM Auth SSL CLRDP collection"""
+    def __init__(self, ltm):
+        super(Ssl_Crldps, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Ssl_Crldp]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:ssl-crldp:ssl-crldpstate': Ssl_Crldp}
+
+
+class Ssl_Crldp(Resource):
+    """BIG-IP® LTM Auth SSL CLRDP resource"""
+    def __init__(self, ssl_crldps):
+        super(Ssl_Crldp, self).__init__(ssl_crldps)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:ssl-crldp:ssl-crldpstate'
+
+
+class Ssl_Ocsps(Collection):
+    """BIG-IP® LTM Auth SSL OCSP collection"""
+    def __init__(self, ltm):
+        super(Ssl_Ocsps, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Ssl_Ocsp]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:ssl-ocsp:ssl-ocspstate': Ssl_Ocsp}
+
+
+class Ssl_Ocsp(Resource):
+    """BIG-IP® LTM Auth SSL OCSP resource"""
+    def __init__(self, ssl_ocsps):
+        super(Ssl_Ocsp, self).__init__(ssl_ocsps)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:ssl-ocsp:ssl-ocspstate'
+
+
+class Tacacs_s(Collection):
+    """BIG-IP® LTM Auth TACACS+ Server collection"""
+    def __init__(self, ltm):
+        super(Tacacs_s, self).__init__(ltm)
+        self._meta_data['allowed_lazy_attributes'] = [Tacacs]
+        self._meta_data['attribute_registry'] =\
+            {'tm:ltm:auth:tacacs:tacacsstate': Tacacs}
+
+
+class Tacacs(Resource):
+    """BIG-IP® LTM Auth TACACS+ Server resource"""
+    def __init__(self, tacacs_s):
+        super(Tacacs, self).__init__(tacacs_s)
+        self._meta_data['required_json_kind'] =\
+            'tm:ltm:auth:tacacs:tacacsstate'
+        self._meta_data['required_creation_parameters'].update(
+            ('secret', 'server',))


Test patch:
diff --git a/f5/bigip/tm/ltm/test/test_auth.py b/f5/bigip/tm/ltm/test/test_auth.py
new file mode 100644
index 0000000..068557a
--- /dev/null
+++ b/f5/bigip/tm/ltm/test/test_auth.py
@@ -0,0 +1,179 @@
+# coding=utf-8
+#
+#  Copyright 2014-2016 F5 Networks Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from f5.bigip import ManagementRoot
+from f5.bigip.resource import MissingRequiredCreationParameter
+from f5.bigip.resource import UnsupportedMethod
+from f5.bigip.tm.ltm.auth import Crldp_Server
+from f5.bigip.tm.ltm.auth import Kerberos_Delegation
+from f5.bigip.tm.ltm.auth import Ldap
+from f5.bigip.tm.ltm.auth import Ocsp_Responder
+from f5.bigip.tm.ltm.auth import Profile
+from f5.bigip.tm.ltm.auth import Radius
+from f5.bigip.tm.ltm.auth import Radius_Server
+from f5.bigip.tm.ltm.auth import Ssl_Cc_Ldap
+from f5.bigip.tm.ltm.auth import Ssl_Crldp
+from f5.bigip.tm.ltm.auth import Ssl_Ocsp
+from f5.bigip.tm.ltm.auth import Tacacs
+import mock
+import pytest
+from six import iterkeys
+
+
+class HelperTest(object):
+    def __init__(self, collection_name):
+        self.partition = 'Common'
+        self.lowered = collection_name.lower()
+        self.test_name = 'fake_' + self.urielementname()
+        self.authkinds = {
+            'crldp_server': 'tm:ltm:auth:crldp-server:crldp-serverstate',
+            'kerberos_delegation':
+                'tm:ltm:auth:kerberos-delegation:kerberos-delegationstate',
+            'ldap': 'tm:ltm:auth:ldap:ldapstate',
+            'ocsp_responder': 'tm:ltm:auth:ocsp-responder:ocsp-responderstate',
+            'profile': 'tm:ltm:auth:profile:profilestate',
+            'radius': 'tm:ltm:auth:radius:radiusstate',
+            'radius_server': 'tm:ltm:auth:radius-server:radius-serverstate',
+            'ssl_cc_ldap': 'tm:ltm:auth:ssl-cc-ldap:ssl-cc-ldapstate',
+            'ssl_crldp': 'tm:ltm:auth:ssl-crldp:ssl-crldpstate',
+            'ssl_ocsp': 'tm:ltm:auth:ssl-ocsp:ssl-ocspstate',
+            'tacacs': 'tm:ltm:auth:tacacs:tacacsstate'
+            }
+
+    def urielementname(self):
+        if self.lowered[-2:] == '_s':
+            endind = 2
+        else:
+            endind = 1
+        return self.lowered[:-endind]
+
+    def set_resources(self, fakeicontrolsession_v12):
+        mr = ManagementRoot('192.168.1.1', 'admin', 'admin')
+        resourcecollection =\
+            getattr(getattr(getattr(mr.tm, 'ltm'), 'auth'),
+                    self.lowered)
+        resource1 = getattr(resourcecollection, self.urielementname())
+        resource2 = getattr(resourcecollection, self.urielementname())
+        return resource1, resource2
+
+    def set_collections(self, fakeicontrolsession_v12):
+        mr = ManagementRoot('192.168.1.1', 'admin', 'admin')
+        resourcecollection =\
+            getattr(getattr(getattr(mr.tm, 'ltm'), 'auth'),
+                    self.lowered)
+        return resourcecollection
+
+    def test_collections(self, fakeicontrolsession_v12, klass):
+        rc = self.set_collections(fakeicontrolsession_v12)
+        test_meta = rc._meta_data['attribute_registry']
+        test_meta2 = rc._meta_data['allowed_lazy_attributes']
+        kind = self.authkinds[self.urielementname()]
+        assert kind in list(iterkeys(test_meta))
+        assert klass in test_meta2
+
+    def test_create_two(self, fakeicontrolsession_v12):
+        r1, r2, = self.set_resources(fakeicontrolsession_v12)
+        assert r1 is not r2
+
+    def test_create_no_args(self, fakeicontrolsession_v12):
+        r1, r2, = self.set_resources(fakeicontrolsession_v12)
+        del r2
+        with pytest.raises(MissingRequiredCreationParameter):
+            r1.create()
+
+
+def test_crldp_server(fakeicontrolsession_v12):
+    a = HelperTest('Crldp_Servers')
+    a.test_collections(fakeicontrolsession_v12, Crldp_Server)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_kerberos_kelegation(fakeicontrolsession_v12):
+    a = HelperTest('Kerberos_Delegations')
+    a.test_collections(fakeicontrolsession_v12, Kerberos_Delegation)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_ldap(fakeicontrolsession_v12):
+    a = HelperTest('Ldaps')
+    a.test_collections(fakeicontrolsession_v12, Ldap)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_ocsp_responder(fakeicontrolsession_v12):
+    a = HelperTest('Ocsp_Responders')
+    a.test_collections(fakeicontrolsession_v12, Ocsp_Responder)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+class TestProfile(object):
+    def test_update_profile_raises(self):
+        profile_resource = Profile(mock.MagicMock())
+        with pytest.raises(UnsupportedMethod):
+            profile_resource.update()
+
+    def test_profile(self, fakeicontrolsession_v12):
+        a = HelperTest('Profiles')
+        a.test_collections(fakeicontrolsession_v12, Profile)
+        a.test_create_two(fakeicontrolsession_v12)
+        a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_radius(fakeicontrolsession_v12):
+    a = HelperTest('Radius_s')
+    a.test_collections(fakeicontrolsession_v12, Radius)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_radius_server(fakeicontrolsession_v12):
+    a = HelperTest('Radius_Servers')
+    a.test_collections(fakeicontrolsession_v12, Radius_Server)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_ssl_cc_ldap(fakeicontrolsession_v12):
+    a = HelperTest('Ssl_Cc_Ldaps')
+    a.test_collections(fakeicontrolsession_v12, Ssl_Cc_Ldap)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_ssl_clrdp(fakeicontrolsession_v12):
+    a = HelperTest('Ssl_Crldps')
+    a.test_collections(fakeicontrolsession_v12, Ssl_Crldp)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_ssl_ocsp(fakeicontrolsession_v12):
+    a = HelperTest('Ssl_Ocsps')
+    a.test_collections(fakeicontrolsession_v12, Ssl_Ocsp)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
+
+
+def test_tacacs(fakeicontrolsession_v12):
+    a = HelperTest('Tacacs_s')
+    a.test_collections(fakeicontrolsession_v12, Tacacs)
+    a.test_create_two(fakeicontrolsession_v12)
+    a.test_create_no_args(fakeicontrolsession_v12)
diff --git a/test/functional/tm/ltm/test_auth.py b/test/functional/tm/ltm/test_auth.py
new file mode 100644
index 0000000..73adce0
--- /dev/null
+++ b/test/functional/tm/ltm/test_auth.py
@@ -0,0 +1,346 @@
+# coding=utf-8
+#
+#  Copyright 2014-2016 F5 Networks Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+import copy
+from f5.bigip.tm.ltm.auth import Crldp_Server
+from f5.bigip.tm.ltm.auth import Kerberos_Delegation
+from f5.bigip.tm.ltm.auth import Ldap
+from f5.bigip.tm.ltm.auth import Ocsp_Responder
+from f5.bigip.tm.ltm.auth import Profile
+from f5.bigip.tm.ltm.auth import Radius
+from f5.bigip.tm.ltm.auth import Radius_Server
+from f5.bigip.tm.ltm.auth import Ssl_Cc_Ldap
+from f5.bigip.tm.ltm.auth import Ssl_Crldp
+from f5.bigip.tm.ltm.auth import Ssl_Ocsp
+from f5.bigip.tm.ltm.auth import Tacacs
+from pprint import pprint as pp
+import pytest
+from requests.exceptions import HTTPError
+from six import iteritems
+TESTDESCRIPTION = "TESTDESCRIPTION"
+pp(__file__)
+
+
+def delete_dependency(mgmt_root, name):
+    try:
+        foo = mgmt_root.tm.ltm.auth.ssl_cc_ldaps.ssl_cc_ldap.load(name=name)
+    except HTTPError as err:
+        if err.response.status_code != 404:
+            raise
+        return
+    foo.delete()
+
+
+def setup_dependency(request, mgmt_root, name, **kwargs):
+    def teardown():
+        delete_dependency(mgmt_root, name)
+    delete_dependency(mgmt_root, name)
+    res = mgmt_root.tm.ltm.auth.ssl_cc_ldaps.ssl_cc_ldap.create(name=name,
+                                                                **kwargs)
+    request.addfinalizer(teardown)
+    return res
+
+
+# Helper class to limit code repetition
+class HelperTest(object):
+    def __init__(self, collection_name):
+        self.partition = 'Common'
+        self.lowered = collection_name.lower()
+        self.test_name = 'fake_' + self.urielementname()
+        self.authkinds = {
+            'crldp_server': 'tm:ltm:auth:crldp-server:crldp-serverstate',
+            'kerberos_delegation':
+                'tm:ltm:auth:kerberos-delegation:kerberos-delegationstate',
+            'ldap': 'tm:ltm:auth:ldap:ldapstate',
+            'ocsp_responder': 'tm:ltm:auth:ocsp-responder:ocsp-responderstate',
+            'profile': 'tm:ltm:auth:profile:profilestate',
+            'radius': 'tm:ltm:auth:radius:radiusstate',
+            'radius_server': 'tm:ltm:auth:radius-server:radius-serverstate',
+            'ssl_cc_ldap': 'tm:ltm:auth:ssl-cc-ldap:ssl-cc-ldapstate',
+            'ssl_crldp': 'tm:ltm:auth:ssl-crldp:ssl-crldpstate',
+            'ssl_ocsp': 'tm:ltm:auth:ssl-ocsp:ssl-ocspstate',
+            'tacacs': 'tm:ltm:auth:tacacs:tacacsstate'
+            }
+
+    def urielementname(self):
+        if self.lowered[-2:] == '_s':
+            endind = 2
+        else:
+            endind = 1
+        return self.lowered[:-endind]
+
+    def delete_resource(self, resource):
+        try:
+            foo = resource.load(name=self.test_name, partition=self.partition)
+        except HTTPError as err:
+            if err.response.status_code != 404:
+                raise
+            return
+        foo.delete()
+
+    def setup_test(self, request, mgmt_root, **kwargs):
+        def teardown():
+            self.delete_resource(resource)
+
+        resourcecollection = \
+            getattr(getattr(getattr(mgmt_root.tm, 'ltm'), 'auth'),
+                    self.lowered)
+        resource = getattr(resourcecollection, self.urielementname())
+        self.delete_resource(resource)
+        created = resource.create(name=self.test_name,
+                                  partition=self.partition,
+                                  **kwargs)
+        request.addfinalizer(teardown)
+        return created, resourcecollection
+
+    def test_MCURDL(self, request, mgmt_root, **kwargs):
+        # Testing create
+        authres, authcollection = self.setup_test(request, mgmt_root, **kwargs)
+        assert authres.name == self.test_name
+        assert authres.fullPath == '/Common/'+self.test_name
+        assert authres.generation and isinstance(authres.generation, int)
+        assert authres.kind == self.authkinds[self.urielementname()]
+
+        # Testing update
+        authres.description = TESTDESCRIPTION
+        pp(authres.raw)
+        authres.update()
+        assert hasattr(authres, 'description')
+        assert authres.description == TESTDESCRIPTION
+
+        # Testing refresh
+        authres.description = ''
+        authres.refresh()
+        assert hasattr(authres, 'description')
+        assert authres.description == TESTDESCRIPTION
+
+        # Testing modify
+        meta_data = authres.__dict__.pop('_meta_data')
+        start_dict = copy.deepcopy(authres.__dict__)
+        authres.__dict__['_meta_data'] = meta_data
+        authres.modify(description='MODIFIED')
+        desc = 'description'
+        for k, v in iteritems(authres.__dict__):
+            if k != desc:
+                start_dict[k] = authres.__dict__[k]
+                assert getattr(authres, k) == start_dict[k]
+            elif k == desc:
+                assert getattr(authres, desc) == 'MODIFIED'
+
+        # Testing load
+        a2 = getattr(authcollection, self.urielementname())
+        authres2 = a2.load(partition=self.partition, name=self.test_name)
+        assert authres.selfLink == authres2.selfLink
+
+    def test_collection(self, request, mgmt_root, **kwargs):
+        authres, authcollection = self.setup_test(request, mgmt_root, **kwargs)
+        assert authres.name == self.test_name
+        assert authres.fullPath == '/Common/' + self.test_name
+        assert authres.generation and isinstance(authres.generation, int)
+        assert authres.kind == self.authkinds[self.urielementname()]
+
+        coll = authcollection.get_collection()
+        assert isinstance(coll, list)
+        assert len(coll)
+
+        if self.lowered == 'crldp_servers':
+            assert isinstance(coll[0], Crldp_Server)
+        elif self.lowered == 'kerberos_delegations':
+            assert isinstance(coll[0], Kerberos_Delegation)
+        elif self.lowered == 'ldaps':
+            assert isinstance(coll[0], Ldap)
+        elif self.lowered == 'ocsp_responders':
+            assert isinstance(coll[0], Ocsp_Responder)
+        elif self.lowered == 'profiles':
+            assert isinstance(coll[0], Profile)
+        elif self.lowered == 'radius_s':
+            assert isinstance(coll[0], Radius)
+        elif self.lowered == 'radius_server_s':
+            assert isinstance(coll[0], Radius_Server)
+        elif self.lowered == 'ssl_cc_ldaps':
+            assert isinstance(coll[0], Ssl_Cc_Ldap)
+        elif self.lowered == 'ssl_crldps':
+            assert isinstance(coll[0], Ssl_Crldp)
+        elif self.lowered == 'ssl_ocsps':
+            assert isinstance(coll[0], Ssl_Ocsp)
+        elif self.lowered == 'tacacs':
+            assert isinstance(coll[0], Tacacs)
+
+    def test_profile_MCRDL(self, request, mgmt_root, **kwargs):
+        # Testing create
+        authres, authcollection = self.setup_test(request, mgmt_root, **kwargs)
+        assert authres.name == self.test_name
+        assert authres.fullPath == '/Common/' + self.test_name
+        assert authres.generation and isinstance(authres.generation, int)
+        assert authres.kind == self.authkinds[self.urielementname()]
+        assert authres.idleTimeout == 300
+
+        # Testing refresh
+        authres.idleTimeout = 0
+        authres.refresh()
+        assert hasattr(authres, 'idleTimeout')
+        assert authres.idleTimeout == 300
+
+        # Testing modify
+        meta_data = authres.__dict__.pop('_meta_data')
+        start_dict = copy.deepcopy(authres.__dict__)
+        authres.__dict__['_meta_data'] = meta_data
+        authres.modify(idleTimeout=100)
+        desc = 'idleTimeout'
+        for k, v in iteritems(authres.__dict__):
+            if k != desc:
+                start_dict[k] = authres.__dict__[k]
+                assert getattr(authres, k) == start_dict[k]
+            elif k == desc:
+                assert getattr(authres, desc) == 100
+
+        # Testing load
+        a2 = getattr(authcollection, self.urielementname())
+        authres2 = a2.load(partition=self.partition, name=self.test_name)
+        assert authres.selfLink == authres2.selfLink
+
+
+class TestCrldpServer(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Crldp_Servers')
+        auth.test_MCURDL(request, mgmt_root, host='10.10.10.10')
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Crldp_Servers')
+        auth.test_collection(request, mgmt_root, host='10.10.10.10')
+
+
+@pytest.mark.skipif(True, reason='this depends on an optional module')
+class TestKerberosDelegation(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Kerberos_Delegations')
+        auth.test_MCURDL(request, mgmt_root,
+                         serverPrincipal='HTTP/fake.com',
+                         clientPrincipal='HTTP/faketoo.com')
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Kerberos_Delegations')
+        auth.test_collection(request, mgmt_root,
+                             serverPrincipal='HTTP/fake.com',
+                             clientPrincipal='HTTP/faketoo.com')
+
+
+@pytest.mark.skipif(True, reason='this depends on an optional module')
+class TestLdap(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Ldaps')
+        auth.test_MCURDL(request, mgmt_root, servers=['10.10.10.10'])
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Ldaps')
+        auth.test_collection(request, mgmt_root, servers=['10.10.10.10'])
+
+
+class TestOcspResponder(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Ocsp_Responders')
+        auth.test_MCURDL(request, mgmt_root)
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Ocsp_Responders')
+        auth.test_collection(request, mgmt_root)
+
+
+class TestProfile(object):
+    def test_MCURDL(self, request, mgmt_root):
+        setup_dependency(request, mgmt_root, 'fakeldap', servers=[
+            '10.10.10.10'], userKey=12345)
+        auth = HelperTest('Profiles')
+        auth.test_profile_MCRDL(request, mgmt_root,
+                                defaultsFrom='/Common/ssl_cc_ldap',
+                                configuration='/Common/fakeldap')
+
+    def test_collection(self, request, mgmt_root):
+        setup_dependency(request, mgmt_root, 'fakeldap', servers=[
+            '10.10.10.10'], userKey=12345)
+        auth = HelperTest('Profiles')
+        auth.test_profile_MCRDL(request, mgmt_root,
+                                defaultsFrom='/Common/ssl_cc_ldap',
+                                configuration='/Common/fakeldap')
+
+
+@pytest.mark.skipif(True, reason='this depends on an optional module')
+class TestRadius(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Radius_s')
+        auth.test_MCURDL(request, mgmt_root)
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Radius_s')
+        auth.test_collection(request, mgmt_root)
+
+
+class TestRadiusServer(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Radius_Servers')
+        auth.test_MCURDL(request, mgmt_root, server='10.10.10.10',
+                         secret='sekrit')
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Radius_Servers')
+        auth.test_collection(request, mgmt_root, server='10.10.10.10',
+                             secret='sekrit')
+
+
+class TestSSLCcLdap(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Ssl_Cc_Ldaps')
+        auth.test_MCURDL(request, mgmt_root, servers=['10.10.10.10'],
+                         userKey=12345)
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Ssl_Cc_Ldaps')
+        auth.test_collection(request, mgmt_root, servers=['10.10.10.10'],
+                             userKey=12345)
+
+
+class TestSSLClrdp(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Ssl_Crldps')
+        auth.test_MCURDL(request, mgmt_root)
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Ssl_Crldps')
+        auth.test_collection(request, mgmt_root)
+
+
+class TestSSLOcsp(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Ssl_Ocsps')
+        auth.test_MCURDL(request, mgmt_root)
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Ssl_Ocsps')
+        auth.test_collection(request, mgmt_root)
+
+
+class TestTacacs(object):
+    def test_MCURDL(self, request, mgmt_root):
+        auth = HelperTest('Radius_Servers')
+        auth.test_MCURDL(request, mgmt_root, server='10.10.10.10',
+                         secret='fortytwo')
+
+    def test_collection(self, request, mgmt_root):
+        auth = HelperTest('Radius_Servers')
+        auth.test_collection(request, mgmt_root, server='10.10.10.10',
+                             secret='fortytwo')