Add a rule for blocking "-" from rand_name call

data_utils.rand_name() appends randam charactors with a hypen like:

 def rand_name(name=''):
     randbits = str(random.randint(1, 0x7fffffff))
     if name:
         return name + '-' + randbits

So it is not necessary to specify a hypen in caller side.
This patch adds a hacking rule for blocking "-" at the end of argument
of rand_name() calls.

Change-Id: I9b9f25dbe5a3ef5ac5900113bcc46e0d911becc9
diff --git a/HACKING.rst b/HACKING.rst
index 04b5eb6..c776c49 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -14,6 +14,7 @@
 - [T105] Tests cannot use setUpClass/tearDownClass
 - [T106] vim configuration should not be kept in source files.
 - [T107] Check that a service tag isn't in the module path
+- [T108] Check no hyphen at the end of rand_name() argument
 - [N322] Method's default argument shouldn't be mutable
 
 Test Data/Configuration
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index b1a9d3b..94aab5b 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -101,7 +101,7 @@
     @test.idempotent_id('2abf8764-309a-4fa9-bc58-201b799817ad')
     def test_create_domain_without_description(self):
         # Create domain only with name
-        d_name = data_utils.rand_name('domain-')
+        d_name = data_utils.rand_name('domain')
         domain = self.client.create_domain(d_name)
         self.addCleanup(self._delete_domain, domain['id'])
         self.assertIn('id', domain)
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 3ebb90d..8a2d797 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -46,7 +46,7 @@
 
     def create_trustor_and_roles(self):
         # create a project that trusts will be granted on
-        self.trustor_project_name = data_utils.rand_name(name='project-')
+        self.trustor_project_name = data_utils.rand_name(name='project')
         project = self.client.create_project(self.trustor_project_name,
                                              domain_id='default')
         self.trustor_project_id = project['id']
diff --git a/tempest/api/messaging/test_queues.py b/tempest/api/messaging/test_queues.py
index 2dac346..a3541b3 100644
--- a/tempest/api/messaging/test_queues.py
+++ b/tempest/api/messaging/test_queues.py
@@ -33,7 +33,7 @@
     @test.idempotent_id('9f1c4c72-80c5-4dac-acf3-188cef42e36c')
     def test_create_delete_queue(self):
         # Create & Delete Queue
-        queue_name = data_utils.rand_name('test-')
+        queue_name = data_utils.rand_name('test')
         _, body = self.create_queue(queue_name)
 
         self.addCleanup(self.client.delete_queue, queue_name)
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 627895e..3396d8f 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -827,8 +827,8 @@
         resp, _ = self.object_client.create_object(src_container_name,
                                                    object_name, data)
         # set object metadata
-        meta_key = data_utils.rand_name(name='test-')
-        meta_value = data_utils.rand_name(name='MetaValue-')
+        meta_key = data_utils.rand_name(name='test')
+        meta_value = data_utils.rand_name(name='MetaValue')
         orig_metadata = {meta_key: meta_value}
         resp, _ = self.object_client.update_object_metadata(src_container_name,
                                                             object_name,
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 24c7c63..ec8e040 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -98,7 +98,7 @@
     @test.idempotent_id('874b35a9-51f1-4258-bec5-cd561b6690d3')
     def test_delete_quota(self):
         # Admin can delete the resource quota set for a tenant
-        tenant_name = data_utils.rand_name('quota_tenant_')
+        tenant_name = data_utils.rand_name('quota_tenant')
         identity_client = self.os_adm.identity_client
         tenant = identity_client.create_tenant(tenant_name)
         tenant_id = tenant['id']
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 29898a9..db6375f 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -27,6 +27,7 @@
 SETUP_TEARDOWN_CLASS_DEFINITION = re.compile(r'^\s+def (setUp|tearDown)Class')
 SCENARIO_DECORATOR = re.compile(r'\s*@.*services\((.*)\)')
 VI_HEADER_RE = re.compile(r"^#\s+vim?:.+")
+RAND_NAME_HYPHEN_RE = re.compile(r".*rand_name\(.+[\-\_][\"\']\)")
 mutable_default_args = re.compile(r"^\s*def .+\((.+=\{\}|.+=\[\])")
 
 
@@ -106,6 +107,21 @@
                             "T107: service tag should not be in path")
 
 
+def no_hyphen_at_end_of_rand_name(logical_line, filename):
+    """Check no hyphen at the end of rand_name() argument
+
+    T108
+    """
+    if './tempest/api/network/' in filename:
+        # Network API tests are migrating from Tempest to Neutron repo now.
+        # So here should avoid network API tests checks.
+        return
+
+    msg = "T108: hyphen should not be specified at the end of rand_name()"
+    if RAND_NAME_HYPHEN_RE.match(logical_line):
+        return 0, msg
+
+
 def no_mutable_default_args(logical_line):
     """Check that mutable object isn't used as default argument
 
@@ -122,4 +138,5 @@
     register(no_setup_teardown_class_for_tests)
     register(no_vi_headers)
     register(service_tags_not_in_module_path)
+    register(no_hyphen_at_end_of_rand_name)
     register(no_mutable_default_args)
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index 9fdb394..b2a30e9 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -91,8 +91,8 @@
 
     def _create_sec_group(self):
         sec_grp_cli = self.manager.security_groups_client
-        s_name = data_utils.rand_name('sec_grp-')
-        s_description = data_utils.rand_name('desc-')
+        s_name = data_utils.rand_name('sec_grp')
+        s_description = data_utils.rand_name('desc')
         self.sec_grp = sec_grp_cli.create_security_group(s_name,
                                                          s_description)
         create_rule = sec_grp_cli.create_security_group_rule
diff --git a/tempest/tests/test_hacking.py b/tempest/tests/test_hacking.py
index fd01887..9bc9cfe 100644
--- a/tempest/tests/test_hacking.py
+++ b/tempest/tests/test_hacking.py
@@ -119,6 +119,13 @@
         self.assertFalse(checks.service_tags_not_in_module_path(
             "@test.services('compute')", './tempest/api/image/fake_test.py'))
 
+    def test_no_hyphen_at_end_of_rand_name(self):
+        self.assertIsNone(checks.no_hyphen_at_end_of_rand_name(
+            'data_utils.rand_name("fake-resource")', './tempest/test_foo.py'))
+        self.assertEqual(2, len(list(checks.no_hyphen_at_end_of_rand_name(
+            'data_utils.rand_name("fake-resource-")', './tempest/test_foo.py')
+        )))
+
     def test_no_mutable_default_args(self):
         self.assertEqual(1, len(list(checks.no_mutable_default_args(
             " def function1(para={}):"))))