Преглед изворни кода

Added tests for resource name validation during create

Nuwan Goonasekera пре 8 година
родитељ
комит
b66a1dbae6

+ 39 - 11
cloudbridge/cloud/base/resources.py

@@ -11,6 +11,7 @@ import time
 
 from cloudbridge.cloud.interfaces.exceptions \
     import InvalidConfigurationException
+from cloudbridge.cloud.interfaces.exceptions import InvalidNameException
 from cloudbridge.cloud.interfaces.exceptions import WaitStateException
 from cloudbridge.cloud.interfaces.resources import AttachmentInfo
 from cloudbridge.cloud.interfaces.resources import Bucket
@@ -188,8 +189,17 @@ class BaseCloudResource(CloudResource):
     def __init__(self, provider):
         self.__provider = provider
 
-    def is_valid_resource_name(self, name):
-        return True if self.CB_NAME_PATTERN.match(name) else False
+    @staticmethod
+    def is_valid_resource_name(name):
+        return True if BaseCloudResource.CB_NAME_PATTERN.match(name) else False
+
+    @staticmethod
+    def assert_valid_resource_name(name):
+        if not BaseCloudResource.is_valid_resource_name(name):
+            raise InvalidNameException(
+                u"Invalid name: %s. Name must be at most 63 characters "
+                "long and consist of lowercase letters, numbers, "
+                "underscores, dashes or international characters" % name)
 
     @property
     def _provider(self):
@@ -748,8 +758,17 @@ class BaseBucketObject(BaseCloudResource, BucketObject):
     def __init__(self, provider):
         super(BaseBucketObject, self).__init__(provider)
 
-    def is_valid_resource_name(self, name):
-        return True if self.CB_NAME_PATTERN.match(name) else False
+    @staticmethod
+    def is_valid_resource_name(name):
+        return True if BaseBucketObject.CB_NAME_PATTERN.match(name) else False
+
+    @staticmethod
+    def assert_valid_resource_name(name):
+        if not BaseBucketObject.is_valid_resource_name(name):
+            raise InvalidNameException(
+                u"Invalid object name: %s. Name must match criteria defined "
+                "in: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMeta"
+                "data.html#object-key-guidelines" % name)
 
     def save_content(self, target_stream):
         """
@@ -779,13 +798,22 @@ class BaseBucket(BaseCloudResource, BasePageableObjectMixin, Bucket):
     #
     # NOTE: The following regex is based on: https://stackoverflow.com/questio
     # ns/2063213/regular-expression-for-validating-dns-label-host-name
-    CB_NAME_PATTERN = re.compile(r"^(?![0-9]+$)(?!-)[a-zA-Z0-9-]{,63}(?<!-)$")
+    CB_NAME_PATTERN = re.compile(r"^(?![0-9]+$)(?!-)[a-z0-9-]{3,63}(?<!-)$")
 
     def __init__(self, provider):
         super(BaseBucket, self).__init__(provider)
 
-    def is_valid_resource_name(self, name):
-        return True if self.CB_NAME_PATTERN.match(name) else False
+    @staticmethod
+    def is_valid_resource_name(name):
+        return True if BaseBucket.CB_NAME_PATTERN.match(name) else False
+
+    @staticmethod
+    def assert_valid_resource_name(name):
+        if not BaseBucket.is_valid_resource_name(name):
+            raise InvalidNameException(
+                u"Invalid bucket name: %s. Name must match criteria defined "
+                "in: http://docs.aws.amazon.com/awscloudtrail/latest/userguide"
+                "/cloudtrail-s3-bucket-naming-requirements.html" % name)
 
     def __eq__(self, other):
         return (isinstance(other, Bucket) and
@@ -803,7 +831,7 @@ class BaseBucket(BaseCloudResource, BasePageableObjectMixin, Bucket):
 class BaseNetwork(BaseCloudResource, BaseObjectLifeCycleMixin, Network):
 
     CB_DEFAULT_NETWORK_NAME = os.environ.get('CB_DEFAULT_NETWORK_NAME',
-                                             'CloudBridgeNet')
+                                             'cloudbridge_net')
 
     def __init__(self, provider):
         super(BaseNetwork, self).__init__(provider)
@@ -833,7 +861,7 @@ class BaseNetwork(BaseCloudResource, BaseObjectLifeCycleMixin, Network):
 class BaseSubnet(BaseCloudResource, BaseObjectLifeCycleMixin, Subnet):
 
     CB_DEFAULT_SUBNET_NAME = os.environ.get('CB_DEFAULT_SUBNET_NAME',
-                                            'CloudBridgeSubnet')
+                                            'cloudbridge_subnet')
 
     def __init__(self, provider):
         super(BaseSubnet, self).__init__(provider)
@@ -881,7 +909,7 @@ class BaseFloatingIP(BaseCloudResource, FloatingIP):
 class BaseRouter(BaseCloudResource, Router):
 
     CB_DEFAULT_ROUTER_NAME = os.environ.get('CB_DEFAULT_ROUTER_NAME',
-                                            'CloudBridgeRouter')
+                                            'cloudbridge_router')
 
     def __init__(self, provider):
         super(BaseRouter, self).__init__(provider)
@@ -901,7 +929,7 @@ class BaseInternetGateway(BaseCloudResource, BaseObjectLifeCycleMixin,
                           InternetGateway):
 
     CB_DEFAULT_INET_GATEWAY_NAME = os.environ.get(
-        'CB_DEFAULT_INET_GATEWAY_NAME', 'CloudBridgeInetGateway')
+        'CB_DEFAULT_INET_GATEWAY_NAME', 'cloudbridge_inetgateway')
 
     def __init__(self, provider):
         super(BaseInternetGateway, self).__init__(provider)

+ 2 - 5
cloudbridge/cloud/interfaces/exceptions.py

@@ -44,8 +44,5 @@ class InvalidNameException(CloudBridgeBaseException):
     a cloudbridge resource.An example would be setting uppercase
     letters, which are not allowed in a resource name.
     """
-    def __init__(self, name):
-        super(InvalidNameException, self).__init__(
-            u"Invalid name: %s. Name must be at most 63 characters long"
-            " and consist of lowercase letters, numbers, underscores, dashes"
-            " or international characters" % name)
+    def __init__(self, msg):
+        super(InvalidNameException, self).__init__(msg)

+ 16 - 29
cloudbridge/cloud/providers/aws/resources.py

@@ -29,7 +29,6 @@ from cloudbridge.cloud.base.resources import BaseSnapshot
 from cloudbridge.cloud.base.resources import BaseSubnet
 from cloudbridge.cloud.base.resources import BaseVolume
 from cloudbridge.cloud.base.resources import ClientPagedResultList
-from cloudbridge.cloud.interfaces.exceptions import InvalidNameException
 from cloudbridge.cloud.interfaces.resources import GatewayState
 from cloudbridge.cloud.interfaces.resources import InstanceState
 from cloudbridge.cloud.interfaces.resources import MachineImageState
@@ -261,10 +260,8 @@ class AWSInstance(BaseInstance):
         """
         Set the instance name.
         """
-        if self.is_valid_resource_name(value):
-            self._ec2_instance.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._ec2_instance.add_tag('Name', value)
 
     @property
     def public_ips(self):
@@ -350,6 +347,8 @@ class AWSInstance(BaseInstance):
         """
         Create a new image based on this instance.
         """
+        self.assert_valid_resource_name(name)
+
         image_id = self._ec2_instance.create_image(name)
         # Sometimes, the image takes a while to register, so retry a few times
         # if the image cannot be found
@@ -451,10 +450,8 @@ class AWSVolume(BaseVolume):
         """
         Set the volume name.
         """
-        if self.is_valid_resource_name(value):
-            self._volume.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._volume.add_tag('Name', value)
 
     @property
     def description(self):
@@ -575,10 +572,8 @@ class AWSSnapshot(BaseSnapshot):
         """
         Set the snapshot name.
         """
-        if self.is_valid_resource_name(value):
-            self._snapshot.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._snapshot.add_tag('Name', value)
 
     @property
     def description(self):
@@ -1002,10 +997,8 @@ class AWSNetwork(BaseNetwork):
         """
         Set the network name.
         """
-        if self.is_valid_resource_name(value):
-            self._vpc.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._vpc.add_tag('Name', value)
 
     @property
     def external(self):
@@ -1077,10 +1070,8 @@ class AWSSubnet(BaseSubnet):
         """
         Set the subnet name.
         """
-        if self.is_valid_resource_name(value):
-            self._subnet.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._subnet.add_tag('Name', value)
 
     @property
     def cidr_block(self):
@@ -1163,10 +1154,8 @@ class AWSRouter(BaseRouter):
         """
         Set the router name.
         """
-        if self.is_valid_resource_name(value):
-            self._route_table.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._route_table.add_tag('Name', value)
 
     def refresh(self):
         self._route_table = self._provider.vpc_conn.get_all_route_tables(
@@ -1232,10 +1221,8 @@ class AWSInternetGateway(BaseInternetGateway):
         """
         Set the router name.
         """
-        if self.is_valid_resource_name(value):
-            self._gateway.add_tag('Name', value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._gateway.add_tag('Name', value)
 
     def refresh(self):
         gateways = self._provider.vpc_conn.get_all_internet_gateways([self.id])

+ 20 - 0
cloudbridge/cloud/providers/aws/services.py

@@ -152,6 +152,8 @@ class AWSKeyPairService(BaseKeyPairService):
         :rtype: ``object`` of :class:`.KeyPair`
         :return:  A key pair instance or ``None`` if one was not be created.
         """
+        AWSKeyPair.assert_valid_resource_name(name)
+
         kp = self.provider.ec2_conn.create_key_pair(name)
         if kp:
             return AWSKeyPair(self.provider, kp)
@@ -209,6 +211,8 @@ class AWSSecurityGroupService(BaseSecurityGroupService):
         :rtype: ``object`` of :class:`.SecurityGroup`
         :return:  A SecurityGroup instance or ``None`` if one was not created.
         """
+        AWSSecurityGroup.assert_valid_resource_name(name)
+
         sg = self.provider.ec2_conn.create_security_group(name, description,
                                                           network_id)
         if sg:
@@ -308,6 +312,8 @@ class AWSVolumeService(BaseVolumeService):
         """
         Creates a new volume.
         """
+        AWSVolume.assert_valid_resource_name(name)
+
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         snapshot_id = snapshot.id if isinstance(
             snapshot, AWSSnapshot) and snapshot else snapshot
@@ -368,6 +374,8 @@ class AWSSnapshotService(BaseSnapshotService):
         """
         Creates a new snapshot of a given volume.
         """
+        AWSSnapshot.assert_valid_resource_name(name)
+
         volume_id = volume.id if isinstance(volume, AWSVolume) else volume
 
         ec2_snap = self.provider.ec2_conn.create_snapshot(
@@ -434,6 +442,8 @@ class AWSObjectStoreService(BaseObjectStoreService):
         """
         Create a new bucket.
         """
+        AWSBucket.assert_valid_resource_name(name)
+
         bucket = self.provider.s3_conn.create_bucket(
             name,
             location=location if location else '')
@@ -514,6 +524,8 @@ class AWSInstanceService(BaseInstanceService):
     def create(self, name, image, instance_type, subnet, zone=None,
                key_pair=None, security_groups=None, user_data=None,
                launch_config=None, **kwargs):
+        AWSInstance.assert_valid_resource_name(name)
+
         image_id = image.id if isinstance(image, MachineImage) else image
         instance_size = instance_type.id if \
             isinstance(instance_type, InstanceType) else instance_type
@@ -797,6 +809,8 @@ class AWSNetworkService(BaseNetworkService):
                                      limit=limit, marker=marker)
 
     def create(self, name, cidr_block):
+        AWSNetwork.assert_valid_resource_name(name)
+
         network = self.provider.vpc_conn.create_vpc(cidr_block=cidr_block)
         cb_network = AWSNetwork(self.provider, network)
         if name:
@@ -864,6 +878,8 @@ class AWSSubnetService(BaseSubnetService):
                                      limit=limit, marker=marker)
 
     def create(self, name, network, cidr_block, zone=None):
+        AWSSubnet.assert_valid_resource_name(name)
+
         network_id = network.id if isinstance(network, AWSNetwork) else network
         subnet = self.provider.vpc_conn.create_subnet(network_id, cidr_block,
                                                       availability_zone=zone)
@@ -939,6 +955,8 @@ class AWSRouterService(BaseRouterService):
                                      marker=marker)
 
     def create(self, name, network):
+        AWSRouter.assert_valid_resource_name(name)
+
         network_id = network.id if isinstance(network, AWSNetwork) else network
         router = self.provider.vpc_conn.create_route_table(vpc_id=network_id)
         cb_router = AWSRouter(self.provider, router)
@@ -954,6 +972,8 @@ class AWSGatewayService(BaseGatewayService):
         super(AWSGatewayService, self).__init__(provider)
 
     def get_or_create_inet_gateway(self, name):
+        AWSInternetGateway.assert_valid_resource_name(name)
+
         gateway = self.provider.vpc_conn.create_internet_gateway()
         cb_gateway = AWSInternetGateway(self.provider, gateway)
         cb_gateway.wait_till_ready()

+ 28 - 40
cloudbridge/cloud/providers/openstack/resources.py

@@ -25,7 +25,6 @@ from cloudbridge.cloud.base.resources import BaseSnapshot
 from cloudbridge.cloud.base.resources import BaseSubnet
 from cloudbridge.cloud.base.resources import BaseVolume
 from cloudbridge.cloud.base.resources import ClientPagedResultList
-from cloudbridge.cloud.interfaces.exceptions import InvalidNameException
 from cloudbridge.cloud.interfaces.resources import GatewayState
 from cloudbridge.cloud.interfaces.resources import InstanceState
 from cloudbridge.cloud.interfaces.resources import MachineImageState
@@ -270,11 +269,10 @@ class OpenStackInstance(BaseInstance):
         """
         Set the instance name.
         """
-        if self.is_valid_resource_name(value):
-            self._os_instance.name = value
-            self._os_instance.update(name=value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+
+        self._os_instance.name = value
+        self._os_instance.update(name=value)
 
     @property
     def public_ips(self):
@@ -377,6 +375,8 @@ class OpenStackInstance(BaseInstance):
         """
         Create a new image based on this instance.
         """
+        self.assert_valid_resource_name(name)
+
         image_id = self._os_instance.create_image(name)
         return OpenStackMachineImage(
             self._provider, self._provider.compute.images.get(image_id))
@@ -498,11 +498,9 @@ class OpenStackVolume(BaseVolume):
         """
         Set the volume name.
         """
-        if self.is_valid_resource_name(value):
-            self._volume.name = value
-            self._volume.update(name=value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._volume.name = value
+        self._volume.update(name=value)
 
     @property
     def description(self):
@@ -621,11 +619,9 @@ class OpenStackSnapshot(BaseSnapshot):
         """
         Set the snapshot name.
         """
-        if self.is_valid_resource_name(value):
-            self._snapshot.name = value
-            self._snapshot.update(name=value)
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._snapshot.name = value
+        self._snapshot.update(name=value)
 
     @property
     def description(self):
@@ -719,12 +715,10 @@ class OpenStackNetwork(BaseNetwork):
         """
         Set the network name.
         """
-        if self.is_valid_resource_name(value):
-            self._provider.neutron.update_network(self.id,
-                                                  {'network': {'name': value}})
-            self.refresh()
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._provider.neutron.update_network(self.id,
+                                              {'network': {'name': value}})
+        self.refresh()
 
     @property
     def external(self):
@@ -791,12 +785,10 @@ class OpenStackSubnet(BaseSubnet):
         """
         Set the subnet name.
         """
-        if self.is_valid_resource_name(value):
-            self._provider.neutron.update_subnet(
-                self.id, {'subnet': {'name': value}})
-            self._subnet['name'] = value
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._provider.neutron.update_subnet(
+            self.id, {'subnet': {'name': value}})
+        self._subnet['name'] = value
 
     @property
     def cidr_block(self):
@@ -885,12 +877,10 @@ class OpenStackRouter(BaseRouter):
         """
         Set the router name.
         """
-        if self.is_valid_resource_name(value):
-            self._provider.neutron.update_router(
-                self.id, {'router': {'name': value}})
-            self.refresh()
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._provider.neutron.update_router(
+            self.id, {'router': {'name': value}})
+        self.refresh()
 
     def refresh(self):
         self._router = self._provider.neutron.show_router(self.id)['router']
@@ -963,12 +953,10 @@ class OpenStackInternetGateway(BaseInternetGateway):
     @name.setter
     # pylint:disable=arguments-differ
     def name(self, value):
-        if self.is_valid_resource_name(value):
-            self._provider.neutron.update_network(self.id,
-                                                  {'network': {'name': value}})
-            self.refresh()
-        else:
-            raise InvalidNameException(value)
+        self.assert_valid_resource_name(value)
+        self._provider.neutron.update_network(self.id,
+                                              {'network': {'name': value}})
+        self.refresh()
 
     @property
     def network_id(self):

+ 22 - 0
cloudbridge/cloud/providers/openstack/services.py

@@ -167,6 +167,8 @@ class OpenStackKeyPairService(BaseKeyPairService):
         :rtype: ``object`` of :class:`.KeyPair`
         :return:  A key pair instance or ``None`` if one was not be created.
         """
+        OpenStackKeyPair.assert_valid_resource_name(name)
+
         kp = self.provider.nova.keypairs.create(name)
         if kp:
             return OpenStackKeyPair(self.provider, kp)
@@ -219,6 +221,8 @@ class OpenStackSecurityGroupService(BaseSecurityGroupService):
         :rtype: ``object`` of :class:`.SecurityGroup`
         :return: a SecurityGroup object
         """
+        OpenStackSecurityGroup.assert_valid_resource_name(name)
+
         sg = self.provider.nova.security_groups.create(name, description)
         if sg:
             return OpenStackSecurityGroup(self.provider, sg)
@@ -372,6 +376,8 @@ class OpenStackVolumeService(BaseVolumeService):
         """
         Creates a new volume.
         """
+        OpenStackVolume.assert_valid_resource_name(name)
+
         zone_id = zone.id if isinstance(zone, PlacementZone) else zone
         snapshot_id = snapshot.id if isinstance(
             snapshot, OpenStackSnapshot) and snapshot else snapshot
@@ -429,6 +435,8 @@ class OpenStackSnapshotService(BaseSnapshotService):
         """
         Creates a new snapshot of a given volume.
         """
+        OpenStackSnapshot.assert_valid_resource_name(name)
+
         volume_id = (volume.id if isinstance(volume, OpenStackVolume)
                      else volume)
 
@@ -484,6 +492,8 @@ class OpenStackObjectStoreService(BaseObjectStoreService):
         """
         Create a new bucket.
         """
+        OpenStackBucket.assert_valid_resource_name(name)
+
         self.provider.swift.put_container(name)
         return self.get(name)
 
@@ -561,6 +571,8 @@ class OpenStackInstanceService(BaseInstanceService):
                launch_config=None,
                **kwargs):
         """Create a new virtual machine instance."""
+        OpenStackInstance.assert_valid_resource_name(name)
+
         image_id = image.id if isinstance(image, MachineImage) else image
         instance_size = instance_type.id if \
             isinstance(instance_type, InstanceType) else \
@@ -774,6 +786,8 @@ class OpenStackNetworkService(BaseNetworkService):
                                      limit=limit, marker=marker)
 
     def create(self, name, cidr_block):
+        OpenStackNetwork.assert_valid_resource_name(name)
+
         net_info = {'name': name}
         network = self.provider.neutron.create_network({'network': net_info})
         return OpenStackNetwork(self.provider, network.get('network'))
@@ -804,6 +818,8 @@ class OpenStackNetworkService(BaseNetworkService):
         return [OpenStackRouter(self.provider, r) for r in routers]
 
     def create_router(self, name=None):
+        OpenStackRouter.assert_valid_resource_name(name)
+
         router = self.provider.neutron.create_router(
             {'router': {'name': name}})
         return OpenStackRouter(self.provider, router.get('router'))
@@ -832,6 +848,8 @@ class OpenStackSubnetService(BaseSubnetService):
 
     def create(self, name, network, cidr_block, zone=None):
         """zone param is ignored."""
+        OpenStackSubnet.assert_valid_resource_name(name)
+
         network_id = (network.id if isinstance(network, OpenStackNetwork)
                       else network)
         subnet_info = {'name': name, 'network_id': network_id,
@@ -904,6 +922,8 @@ class OpenStackRouterService(BaseRouterService):
         https://developer.openstack.org/api-ref/networking/v2/
             ?expanded=delete-router-detail,create-router-detail#create-router
         """
+        OpenStackRouter.assert_valid_resource_name(name)
+
         body = {'router': {'name': name}} if name else None
         router = self.provider.neutron.create_router(body)
         return OpenStackRouter(self.provider, router.get('router'))
@@ -915,6 +935,8 @@ class OpenStackGatewayService(BaseGatewayService):
         super(OpenStackGatewayService, self).__init__(provider)
 
     def get_or_create_inet_gateway(self, name):
+        OpenStackInternetGateway.assert_valid_resource_name(name)
+
         for n in self.provider.networking.networks:
             if n.external:
                 return OpenStackInternetGateway(self.provider, n)

+ 31 - 4
test/helpers/standard_interface_tests.py

@@ -131,7 +131,7 @@ def check_obj_name(test, obj):
             obj.name = "hello world"
         # setting upper case characters should raise an exception
         with test.assertRaises(InvalidNameException):
-            obj.name = "hello World"
+            obj.name = "helloWorld"
         # setting special characters should raise an exception
         with test.assertRaises(InvalidNameException):
             obj.name = "hello.world:how_goes_it"
@@ -143,7 +143,6 @@ def check_obj_name(test, obj):
         obj.refresh()
         test.assertEqual(obj.name, VALID_NAME)
         obj.name = original_name
-    pass
 
 
 def check_standard_behaviour(test, service, obj):
@@ -185,9 +184,29 @@ def check_standard_behaviour(test, service, obj):
                                             obj.id))
 
 
+def check_create(test, service, iface, name_prefix,
+                 create_func, cleanup_func):
+
+    # check create with invalid name
+    with test.assertRaises(InvalidNameException):
+        # spaces should raise an exception
+        create_func("hello world")
+    # check create with invalid name
+    with test.assertRaises(InvalidNameException):
+        # uppercase characters should raise an exception
+        create_func("helloWorld")
+    # setting special characters should raise an exception
+    with test.assertRaises(InvalidNameException):
+        create_func("hello.world:how_goes_it")
+    # setting a length > 63 should result in an exception
+    with test.assertRaises(InvalidNameException,
+                           msg="Name of length > 64 should be disallowed"):
+        create_func("a" * 64)
+
+
 def check_crud(test, service, iface, name_prefix,
                create_func, cleanup_func, extra_test_func=None,
-               custom_check_delete=None):
+               custom_check_delete=None, skip_name_check=False):
     """
     Checks crud behaviour of a given cloudbridge service. The create_func will
     be used as a factory function to create a service object and the
@@ -232,10 +251,18 @@ def check_crud(test, service, iface, name_prefix,
     :param custom_check_delete: If provided, this function will be called
                                 instead of the standard check_delete function
                                 to make sure that the object has been deleted.
+
+    :type  skip_name_check: ``boolean``
+    :param skip_name_check:  If True, the invalid name checking will be
+                             skipped.
     """
-    name = "{0}-{1}".format(name_prefix, helpers.get_uuid())
+
     obj = None
     with helpers.cleanup_action(lambda: cleanup_func(obj)):
+        if not skip_name_check:
+            check_create(test, service, iface, name_prefix,
+                         create_func, cleanup_func)
+        name = "{0}-{1}".format(name_prefix, helpers.get_uuid())
         obj = create_func(name)
         if issubclass(iface, ObjectLifeCycleMixin):
             obj.wait_till_ready()

+ 22 - 3
test/test_object_store_service.py

@@ -10,6 +10,7 @@ from test.helpers import ProviderTestBase
 from test.helpers import standard_interface_tests as sit
 from unittest import skip
 
+from cloudbridge.cloud.interfaces.exceptions import InvalidNameException
 from cloudbridge.cloud.interfaces.resources import Bucket
 from cloudbridge.cloud.interfaces.resources import BucketObject
 
@@ -30,8 +31,25 @@ class CloudObjectStoreServiceTestCase(ProviderTestBase):
         def cleanup_bucket(bucket):
             bucket.delete()
 
+        with self.assertRaises(InvalidNameException):
+            # underscores are not allowed in bucket names
+            create_bucket("cb_bucket")
+
+        with self.assertRaises(InvalidNameException):
+            # names of length less than 3 should raise an exception
+            create_bucket("cb")
+
+        with self.assertRaises(InvalidNameException):
+            # names of length less than 63 should raise an exception
+            create_bucket("a" * 64)
+
+        with self.assertRaises(InvalidNameException):
+            # bucket name cannot be an IP address
+            create_bucket("197.10.100.42")
+
         sit.check_crud(self, self.provider.object_store, Bucket,
-                       "cb_crudbucket", create_bucket, cleanup_bucket)
+                       "cb-crudbucket", create_bucket, cleanup_bucket,
+                       skip_name_check=True)
 
     @helpers.skipIfNoService(['object_store'])
     def test_crud_bucket_object(self):
@@ -50,11 +68,12 @@ class CloudObjectStoreServiceTestCase(ProviderTestBase):
             bucket_obj.delete()
 
         with helpers.cleanup_action(lambda: test_bucket.delete()):
-            name = "cb_crudbucketobj-{0}".format(uuid.uuid4())
+            name = "cb-crudbucketobj-{0}".format(uuid.uuid4())
             test_bucket = self.provider.object_store.create(name)
+
             sit.check_crud(self, test_bucket, BucketObject,
                            "cb_bucketobj", create_bucket_obj,
-                           cleanup_bucket_obj)
+                           cleanup_bucket_obj, skip_name_check=True)
 
     @helpers.skipIfNoService(['object_store'])
     def test_crud_bucket_object_properties(self):