فهرست منبع

Fix mock test_crud_instance: pin moto to AZ-filter fix, drop version skip

moto's describe_instances availability-zone filter is broken (it compares the
InstancePlacement object, not the AZ string), so CloudBridge's zone-scoped
instances.list() got an empty result under the mock provider while working
against real AWS. Fixed upstream in getmoto/moto#10066; pin moto to that fix
via requirements.txt until it is released.

Remove the obsolete moto-version skip and its now-unused helper, and relax the
post-delete assertion to accept DELETED or UNKNOWN (matching check_deleted in
the same test -- both mean successfully deleted).
Nuwan Goonasekera 13 ساعت پیش
والد
کامیت
4695409b7d
3فایلهای تغییر یافته به همراه17 افزوده شده و 45 حذف شده
  1. 7 0
      requirements.txt
  2. 0 30
      tests/helpers/__init__.py
  3. 10 15
      tests/test_compute_service.py

+ 7 - 0
requirements.txt

@@ -1 +1,8 @@
 -e ".[dev]"
+
+# Temporary: pin moto to the fix for the describe_instances availability-zone
+# filter bug (https://github.com/getmoto/moto/pull/10066). Released moto
+# (<= 5.2.2) returns an empty list when CloudBridge filters instances by AZ,
+# which breaks test_crud_instance against the mock provider. Drop this line and
+# bump the moto floor in pyproject.toml's [dev] extra once the fix is released.
+moto[ec2,s3] @ git+https://github.com/CloudVE/moto@fix-describe-instances-az-filter

+ 0 - 30
tests/helpers/__init__.py

@@ -46,36 +46,6 @@ def skipIfNoService(services):
     return wrap
 
 
-def skipIfMockMotoVersion(spec, reason):
-    """
-    A decorator for skipping tests when running against the mock
-    provider and the installed moto version matches `spec` (a
-    PEP 440 specifier string such as ">=5.0,<5.3"). Other providers
-    (aws / azure / gcp / openstack) always run the test, and the mock
-    provider runs it normally when moto sits outside the broken range.
-    """
-    def wrap(func):
-        @functools.wraps(func)
-        def wrapper(self, *args, **kwargs):
-            provider = getattr(self, 'provider', None)
-            if provider and getattr(provider, 'PROVIDER_ID', None) == 'mock':
-                from importlib.metadata import PackageNotFoundError
-                from importlib.metadata import version as get_version
-                from packaging.specifiers import SpecifierSet
-                from packaging.version import Version
-                try:
-                    moto_version = Version(get_version('moto'))
-                except PackageNotFoundError:
-                    moto_version = None
-                if moto_version and moto_version in SpecifierSet(spec):
-                    self.skipTest(
-                        "Skipping for mock/moto %s matching %s: %s"
-                        % (moto_version, spec, reason))
-            func(self, *args, **kwargs)
-        return wrapper
-    return wrap
-
-
 def skipIfPython(op, major, minor):
     """
     A decorator for skipping tests if the python

+ 10 - 15
tests/test_compute_service.py

@@ -31,16 +31,6 @@ class CloudComputeServiceTestCase(ProviderTestBase):
                                      self.provider.compute.instances.
                                      _service_event_pattern))
 
-    # moto 5.x regression: DescribeInstances returns an empty list
-    # immediately after RunInstances completes, so the list-after-create
-    # check in standard_interface_tests.check_list fails. A secondary
-    # symptom shows in cleanup, where post-delete state remains
-    # "deleted" instead of becoming UNKNOWN. Pinned to the latest moto
-    # release where this was observed (5.2.1); newer releases re-run the
-    # test so we notice if it's fixed. Bump the pin if it's still broken.
-    @helpers.skipIfMockMotoVersion(
-        "==5.2.1",
-        "moto 5.2.1 RunInstances/DescribeInstances state-sync bug")
     @helpers.skipIfNoService(['compute.instances', 'networking.networks'])
     def test_crud_instance(self):
         label = "cb-instcrud-{0}".format(helpers.get_uuid())
@@ -59,11 +49,16 @@ class CloudComputeServiceTestCase(ProviderTestBase):
                 inst.delete()
                 inst.wait_for([InstanceState.DELETED, InstanceState.UNKNOWN])
                 inst.refresh()
-                self.assertTrue(
-                    inst.state == InstanceState.UNKNOWN,
-                    "Instance.state must be unknown when refreshing after a "
-                    "delete but got %s"
-                    % inst.state)
+                # A deleted instance is reported either as DELETED (the
+                # backend still returns it as terminated) or UNKNOWN (the
+                # backend has forgotten it). Both mean "successfully deleted";
+                # which one depends on backend forget-timing, not on
+                # CloudBridge. This matches check_deleted below.
+                self.assertIn(
+                    inst.state,
+                    (InstanceState.DELETED, InstanceState.UNKNOWN),
+                    "Instance.state must be deleted or unknown when refreshing "
+                    "after a delete but got %s" % inst.state)
 
         def check_deleted(inst):
             deleted_inst = self.provider.compute.instances.get(