Merge "Expand OpenStackSecurityGroup class tests."
authorSteven Pisarski <s.pisarski@cablelabs.com>
Thu, 27 Jul 2017 14:38:50 +0000 (14:38 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Thu, 27 Jul 2017 14:38:50 +0000 (14:38 +0000)
docs/how-to-use/APITests.rst
docs/how-to-use/IntegrationTests.rst
docs/how-to-use/LibraryUsage.rst
snaps/domain/project.py
snaps/domain/test/project_tests.py
snaps/openstack/create_keypairs.py
snaps/openstack/os_credentials.py
snaps/openstack/tests/create_keypairs_tests.py
snaps/openstack/tests/create_project_tests.py
snaps/openstack/utils/keystone_utils.py

index 68a1a07..ff0ab45 100644 (file)
@@ -91,6 +91,10 @@ create_project_tests.py - CreateProjectSuccessTests
 +----------------------------------+---------------+-----------------------------------------------------------+
 | Test Name                        | Keystone API  | Description                                               |
 +==================================+===============+===========================================================+
+| test_create_project_bad_domain   | 3             | Ensures that keystone v3 clients using the domain ID      |
+|                                  |               | project setting project creation will fail with an invalid|
+|                                  |               | domain id/name                                            |
++----------------------------------+---------------+-----------------------------------------------------------+
 | test_create_project              | 2 & 3         | Tests the creation of a project via the OpenStackProject  |
 |                                  |               | class                                                     |
 +----------------------------------+---------------+-----------------------------------------------------------+
index 92a5301..4cdd94f 100644 (file)
@@ -118,6 +118,9 @@ create_keypairs_tests.py - CreateKeypairsTests
 | test_create_keypair_only              | 2             | Ensures that a keypair object can be created simply by    |
 |                                       |               | only configuring a name                                   |
 +---------------------------------------+---------------+-----------------------------------------------------------+
+| test_create_keypair_large_key         | 2             | Ensures that a keypair object can be created with a large |
+|                                       |               | key of 10000 bytes                                        |
++---------------------------------------+---------------+-----------------------------------------------------------+
 | test_create_delete_keypair            | 2             | Ensures that a keypair object is deleted via              |
 |                                       |               | OpenStackKeypair.clean() and subsequent calls do not      |
 |                                       |               | result in exceptions                                      |
index 0a137ba..353891e 100644 (file)
@@ -31,7 +31,7 @@ attributes are listed below:
 -  project\_name (aka. tenant\_name)
 -  identity\_api\_version (for obtaining Keystone authorization token.
    Versions 2.0 & v3 only validated.)
--  image\_api\_version (Glance version 1 currently only validated)
+-  image\_api\_version (Glance version 1 & 2 only validated)
 -  network\_api\_version (Neutron version 2 currently only validated)
 -  compute\_api\_version (Nova version 2 currently only validated)
 -  heat\_api\_version (Heat version 1 currently only validated)
@@ -39,6 +39,7 @@ attributes are listed below:
 -  project\_domain\_id (default='default')
 -  interface (default='admin', used to specify the endpoint type for keystone: public, admin, internal)
 -  cacert (default=False, expected values T|F to denote server certificate verification, else value contains the path to an HTTPS certificate)
+-  region_name (The region name default=None)
 -  proxy\_settings
 
    -  host (the HTTP proxy host)
index 818645b..73357c7 100644 (file)
@@ -19,14 +19,16 @@ class Project:
     SNAPS domain object for Projects. Should contain attributes that
     are shared amongst cloud providers
     """
-    def __init__(self, name, project_id):
+    def __init__(self, name, project_id, domain_id=None):
         """
         Constructor
         :param name: the project's name
         :param project_id: the project's id
+        :param domain_id: the project's domain id
         """
         self.name = name
         self.id = project_id
+        self.domain_id = domain_id
 
     def __eq__(self, other):
         return self.name == other.name and self.id == other.id
index 4056bba..73939f0 100644 (file)
@@ -22,12 +22,26 @@ class ProjectDomainObjectTests(unittest.TestCase):
     Tests the construction of the snaps.domain.test.Project class
     """
 
-    def test_construction_positional(self):
+    def test_construction_positional_minimal(self):
         project = Project('foo', '123-456')
         self.assertEqual('foo', project.name)
         self.assertEqual('123-456', project.id)
+        self.assertIsNone(project.domain_id)
 
-    def test_construction_named(self):
+    def test_construction_positional_all(self):
+        project = Project('foo', '123-456', 'hello')
+        self.assertEqual('foo', project.name)
+        self.assertEqual('123-456', project.id)
+        self.assertEqual('hello', project.domain_id)
+
+    def test_construction_named_minimal(self):
         project = Project(project_id='123-456', name='foo')
         self.assertEqual('foo', project.name)
         self.assertEqual('123-456', project.id)
+        self.assertIsNone(project.domain_id)
+
+    def test_construction_named_all(self):
+        project = Project(domain_id='hello', project_id='123-456', name='foo')
+        self.assertEqual('foo', project.name)
+        self.assertEqual('123-456', project.id)
+        self.assertEqual('hello', project.domain_id)
index 16374ad..c81fef5 100644 (file)
@@ -68,13 +68,13 @@ class OpenStackKeypair:
                     self.keypair_settings.public_filepath)
 
                 if self.keypair_settings.delete_on_clean is not None:
-                    self.__delete_keys_on_clean = self.keypair_settings.delete_on_clean
+                    delete_on_clean = self.keypair_settings.delete_on_clean
+                    self.__delete_keys_on_clean = delete_on_clean
                 else:
                     self.__delete_keys_on_clean = False
             else:
                 logger.info("Creating new keypair")
-                # TODO - Make this value configurable
-                keys = nova_utils.create_keys(1024)
+                keys = nova_utils.create_keys(self.keypair_settings.key_size)
                 self.__keypair = nova_utils.upload_keypair(
                     self.__nova, self.keypair_settings.name,
                     nova_utils.public_key_openssh(keys))
@@ -83,7 +83,8 @@ class OpenStackKeypair:
                     self.keypair_settings.private_filepath)
 
                 if self.keypair_settings.delete_on_clean is not None:
-                    self.__delete_keys_on_clean = self.keypair_settings.delete_on_clean
+                    delete_on_clean = self.keypair_settings.delete_on_clean
+                    self.__delete_keys_on_clean = delete_on_clean
                 else:
                     self.__delete_keys_on_clean = True
         elif self.__keypair and not os.path.isfile(
@@ -137,6 +138,8 @@ class KeypairSettings:
                                 public key file is or will be stored
         :param private_filepath: The path where the generated private key file
                                  will be stored
+        :param key_size: The number of bytes for the key size when it needs to
+                         be generated (Must be >=512 default 1024)
         :param delete_on_clean: when True, the key files will be deleted when
                                 OpenStackKeypair#clean() is called
         :return:
@@ -145,6 +148,7 @@ class KeypairSettings:
         self.name = kwargs.get('name')
         self.public_filepath = kwargs.get('public_filepath')
         self.private_filepath = kwargs.get('private_filepath')
+        self.key_size = int(kwargs.get('key_size', 1024))
 
         if kwargs.get('delete_on_clean') is not None:
             if isinstance(kwargs.get('delete_on_clean'), bool):
@@ -157,6 +161,9 @@ class KeypairSettings:
         if not self.name:
             raise KeypairSettingsError('Name is a required attribute')
 
+        if self.key_size < 512:
+            raise KeypairSettingsError('key_size must be >=512')
+
 
 class KeypairSettingsError(Exception):
     """
index 3054478..0cecfa5 100644 (file)
@@ -42,8 +42,8 @@ class OSCreds:
                                     clients
         :param heat_api_version: The OpenStack's API version to use for Heat
                                     clients
-        :param user_domain_id: Used for v3 APIs
-        :param project_domain_id: Used for v3 APIs
+        :param user_domain_id: Used for v3 APIs (default='default')
+        :param project_domain_id: Used for v3 APIs (default='default')
         :param interface: Used to specify the endpoint type for keystone as
                           public, admin, internal
         :param proxy_settings: instance of os_credentials.ProxySettings class
index 2824c34..0b35095 100644 (file)
@@ -39,9 +39,14 @@ class KeypairSettingsUnitTests(unittest.TestCase):
         with self.assertRaises(KeypairSettingsError):
             KeypairSettings(**dict())
 
+    def test_small_key_size(self):
+        with self.assertRaises(KeypairSettingsError):
+            KeypairSettings(name='foo', key_size=511)
+
     def test_name_only(self):
         settings = KeypairSettings(name='foo')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertIsNone(settings.public_filepath)
         self.assertIsNone(settings.private_filepath)
         self.assertIsNone(settings.delete_on_clean)
@@ -49,6 +54,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_config_with_name_only(self):
         settings = KeypairSettings(**{'name': 'foo'})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertIsNone(settings.public_filepath)
         self.assertIsNone(settings.private_filepath)
         self.assertIsNone(settings.delete_on_clean)
@@ -56,6 +62,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_name_pub_only(self):
         settings = KeypairSettings(name='foo', public_filepath='/foo/bar.pub')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertIsNone(settings.private_filepath)
         self.assertIsNone(settings.delete_on_clean)
@@ -64,6 +71,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
         settings = KeypairSettings(
             **{'name': 'foo', 'public_filepath': '/foo/bar.pub'})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertIsNone(settings.private_filepath)
         self.assertIsNone(settings.delete_on_clean)
@@ -71,6 +79,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_name_priv_only(self):
         settings = KeypairSettings(name='foo', private_filepath='/foo/bar')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertIsNone(settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertIsNone(settings.delete_on_clean)
@@ -79,6 +88,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
         settings = KeypairSettings(
             **{'name': 'foo', 'private_filepath': '/foo/bar'})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertIsNone(settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertIsNone(settings.delete_on_clean)
@@ -86,8 +96,10 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_all_delete_bool(self):
         settings = KeypairSettings(
             name='foo', public_filepath='/foo/bar.pub',
-            private_filepath='/foo/bar', delete_on_clean=True)
+            private_filepath='/foo/bar', delete_on_clean=True,
+            key_size=999)
         self.assertEqual('foo', settings.name)
+        self.assertEqual(999, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertTrue(settings.delete_on_clean)
@@ -97,6 +109,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
             name='foo', public_filepath='/foo/bar.pub',
             private_filepath='/foo/bar', delete_on_clean='True')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertTrue(settings.delete_on_clean)
@@ -106,6 +119,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
             name='foo', public_filepath='/foo/bar.pub',
             private_filepath='/foo/bar', delete_on_clean='true')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertTrue(settings.delete_on_clean)
@@ -115,6 +129,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
             name='foo', public_filepath='/foo/bar.pub',
             private_filepath='/foo/bar', delete_on_clean='False')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertFalse(settings.delete_on_clean)
@@ -122,8 +137,10 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_all_delete_str_false_lc(self):
         settings = KeypairSettings(
             name='foo', public_filepath='/foo/bar.pub',
-            private_filepath='/foo/bar', delete_on_clean='false')
+            private_filepath='/foo/bar', delete_on_clean='false',
+            key_size='999')
         self.assertEqual('foo', settings.name)
+        self.assertEqual(999, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertFalse(settings.delete_on_clean)
@@ -131,8 +148,10 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_config_all_delete_false_bool(self):
         settings = KeypairSettings(
             **{'name': 'foo', 'public_filepath': '/foo/bar.pub',
-               'private_filepath': '/foo/bar', 'delete_on_clean': False})
+               'private_filepath': '/foo/bar', 'delete_on_clean': False,
+               'key_size': 999})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(999, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertFalse(settings.delete_on_clean)
@@ -142,6 +161,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
             **{'name': 'foo', 'public_filepath': '/foo/bar.pub',
                'private_filepath': '/foo/bar', 'delete_on_clean': 'False'})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertFalse(settings.delete_on_clean)
@@ -151,6 +171,7 @@ class KeypairSettingsUnitTests(unittest.TestCase):
             **{'name': 'foo', 'public_filepath': '/foo/bar.pub',
                'private_filepath': '/foo/bar', 'delete_on_clean': 'false'})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(1024, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertFalse(settings.delete_on_clean)
@@ -158,8 +179,10 @@ class KeypairSettingsUnitTests(unittest.TestCase):
     def test_config_all_delete_false_str_foo(self):
         settings = KeypairSettings(
             **{'name': 'foo', 'public_filepath': '/foo/bar.pub',
-               'private_filepath': '/foo/bar', 'delete_on_clean': 'foo'})
+               'private_filepath': '/foo/bar', 'delete_on_clean': 'foo',
+               'key_size': '999'})
         self.assertEqual('foo', settings.name)
+        self.assertEqual(999, settings.key_size)
         self.assertEqual('/foo/bar.pub', settings.public_filepath)
         self.assertEqual('/foo/bar', settings.private_filepath)
         self.assertFalse(settings.delete_on_clean)
@@ -213,6 +236,19 @@ class CreateKeypairsTests(OSIntegrationTestCase):
                                             self.keypair_creator.get_keypair())
         self.assertEqual(self.keypair_creator.get_keypair(), keypair)
 
+    def test_create_keypair_large_key(self):
+        """
+        Tests the creation of a generated keypair without saving to file
+        :return:
+        """
+        self.keypair_creator = OpenStackKeypair(self.os_creds, KeypairSettings(
+            name=self.keypair_name, key_size=10000))
+        self.keypair_creator.create()
+
+        keypair = nova_utils.keypair_exists(self.nova,
+                                            self.keypair_creator.get_keypair())
+        self.assertEqual(self.keypair_creator.get_keypair(), keypair)
+
     def test_create_delete_keypair(self):
         """
         Tests the creation then deletion of an OpenStack keypair to ensure
index f2af0d9..f388ba5 100644 (file)
@@ -15,6 +15,8 @@
 import unittest
 import uuid
 
+from keystoneclient.exceptions import BadRequest
+
 from snaps.openstack.create_project import (
     OpenStackProject, ProjectSettings, ProjectSettingsError)
 from snaps.openstack.create_security_group import OpenStackSecurityGroup
@@ -98,6 +100,19 @@ class CreateProjectSuccessTests(OSComponentTestCase):
         if self.project_creator:
             self.project_creator.clean()
 
+    def test_create_project_bad_domain(self):
+        """
+        Tests the creation of an OpenStack project with an invalid domain
+        value. This test will not do anything with a keystone v2.0 client.
+        """
+        if self.keystone.version != keystone_utils.V2_VERSION_STR:
+            self.project_settings.domain = 'foo'
+            self.project_creator = OpenStackProject(self.os_creds,
+                                                    self.project_settings)
+
+            with self.assertRaises(BadRequest):
+                self.project_creator.create()
+
     def test_create_project(self):
         """
         Tests the creation of an OpenStack project.
@@ -111,6 +126,8 @@ class CreateProjectSuccessTests(OSComponentTestCase):
             keystone=self.keystone, project_name=self.project_settings.name)
         self.assertIsNotNone(retrieved_project)
         self.assertEqual(created_project, retrieved_project)
+        self.assertTrue(validate_project(self.keystone, self.project_settings,
+                                         created_project))
 
     def test_create_project_2x(self):
         """
@@ -130,6 +147,8 @@ class CreateProjectSuccessTests(OSComponentTestCase):
         project2 = OpenStackProject(self.os_creds,
                                     self.project_settings).create()
         self.assertEqual(retrieved_project, project2)
+        self.assertTrue(validate_project(self.keystone, self.project_settings,
+                                         created_project))
 
     def test_create_delete_project(self):
         """
@@ -147,7 +166,8 @@ class CreateProjectSuccessTests(OSComponentTestCase):
 
         self.assertIsNone(self.project_creator.get_project())
 
-        # TODO - Expand tests
+        self.assertTrue(validate_project(self.keystone, self.project_settings,
+                                         created_project))
 
 
 class CreateProjectUserTests(OSComponentTestCase):
@@ -254,3 +274,19 @@ class CreateProjectUserTests(OSComponentTestCase):
 
             self.assertEqual(self.project_creator.get_project().id,
                              sec_grp.project_id)
+
+
+def validate_project(keystone, project_settings, project):
+    """
+    Validates that the project_settings used to create the project have been
+    properly set
+    :param keystone: the keystone client for version checking
+    :param project_settings: the settings used to create the project
+    :param project: the SNAPS-OO Project domain object
+    :return: T/F
+    """
+    if keystone.version == keystone_utils.V2_VERSION_STR:
+        return project_settings.name == project.name
+    else:
+        return (project_settings.name == project.name and
+                project_settings.domain == project.domain_id)
index 8446df0..e070a49 100644 (file)
@@ -127,8 +127,12 @@ def get_project(keystone=None, os_creds=None, project_name=None):
         projects = keystone.projects.list(**{'name': project_name})
 
     for project in projects:
+        domain_id = None
+        if keystone.version != V2_VERSION_STR:
+            domain_id = project.domain_id
         if project.name == project_name:
-            return Project(name=project.name, project_id=project.id)
+            return Project(name=project.name, project_id=project.id,
+                           domain_id=domain_id)
 
     return None
 
@@ -140,6 +144,8 @@ def create_project(keystone, project_settings):
     :param project_settings: the project configuration
     :return: SNAPS-OO Project domain object
     """
+    domain_id = None
+
     if keystone.version == V2_VERSION_STR:
         os_project = keystone.tenants.create(
             project_settings.name, project_settings.description,
@@ -149,8 +155,10 @@ def create_project(keystone, project_settings):
             project_settings.name, project_settings.domain,
             description=project_settings.description,
             enabled=project_settings.enabled)
+        domain_id = os_project.domain_id
 
-    return Project(name=os_project.name, project_id=os_project.id)
+    return Project(
+        name=os_project.name, project_id=os_project.id, domain_id=domain_id)
 
 
 def delete_project(keystone, project):