From 18ec0c54673c5f0c44229e2c72b718948a112a2e Mon Sep 17 00:00:00 2001 From: Hans Donner Date: Sun, 12 Mar 2023 17:54:50 +0100 Subject: [PATCH] Techdebt: skip tests when docker is not running (#6026) --- Makefile | 6 ++-- moto/awslambda/models.py | 2 +- moto/settings.py | 3 ++ requirements-tests.txt | 1 + setup.cfg | 3 +- tests/markers.py | 8 +++++ .../test_lambda_eventsourcemapping.py | 6 ++++ tests/test_awslambda/test_lambda_invoke.py | 9 +++++ tests/test_batch/test_batch_jobs.py | 13 +++++++ tests/test_batch_simple/test_batch_jobs.py | 16 ++++----- .../test_cloudformation_custom_resources.py | 2 ++ .../test_cloudformation_stack_integration.py | 2 ++ tests/test_core/test_docker.py | 36 +++++++++++++++++++ .../test_events_lambdatriggers_integration.py | 2 ++ tests/test_logs/test_integration.py | 4 +++ .../state_manager/test_batch_integration.py | 2 ++ tests/test_s3/test_s3_lambda_integration.py | 2 ++ tests/test_secretsmanager/test_server.py | 2 ++ tests/test_sqs/test_sqs_integration.py | 3 ++ 19 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 tests/markers.py create mode 100644 tests/test_core/test_docker.py diff --git a/Makefile b/Makefile index 151af6849..ac8a9016a 100644 --- a/Makefile +++ b/Makefile @@ -36,10 +36,10 @@ format: test-only: rm -f .coverage rm -rf cover - pytest -sv --cov=moto --cov-report xml ./tests/ $(TEST_EXCLUDE) + pytest -sv -rs --cov=moto --cov-report xml ./tests/ $(TEST_EXCLUDE) # https://github.com/aws/aws-xray-sdk-python/issues/196 - Run these tests separately without Coverage enabled - pytest -sv ./tests/test_xray - MOTO_CALL_RESET_API=false pytest --cov=moto --cov-report xml --cov-append -n 4 $(PARALLEL_TESTS) + pytest -sv -rs ./tests/test_xray + MOTO_CALL_RESET_API=false pytest -rs --cov=moto --cov-report xml --cov-append -n 4 $(PARALLEL_TESTS) test: lint test-only diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 168cf0894..c5ca3f294 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -59,7 +59,6 @@ from tempfile import TemporaryDirectory logger = logging.getLogger(__name__) - docker_3 = docker.__version__[0] >= "3" @@ -830,6 +829,7 @@ class LambdaFunction(CloudFormationModel, DockerModel): except docker.errors.DockerException as e: # Docker itself is probably not running - there will be no Lambda-logs to handle msg = f"error running docker: {e}" + logger.error(msg) self.save_logs(msg) return msg, True, "" diff --git a/moto/settings.py b/moto/settings.py index 9467f63c5..865a791e0 100644 --- a/moto/settings.py +++ b/moto/settings.py @@ -32,6 +32,9 @@ ENABLE_AMI_VALIDATION = bool(os.environ.get("MOTO_ENABLE_AMI_VALIDATION", False) PRETTIFY_RESPONSES = bool(os.environ.get("MOTO_PRETTIFY_RESPONSES", False)) +# Fully skip test that require docker +SKIP_REQUIRES_DOCKER = bool(os.environ.get("TESTS_SKIP_REQUIRES_DOCKER", False)) + def get_sf_execution_history_type(): """ diff --git a/requirements-tests.txt b/requirements-tests.txt index 2bcfe7cf2..f01abcfeb 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -1,6 +1,7 @@ coverage pytest pytest-cov +pytest-ordering pytest-xdist surer freezegun diff --git a/setup.cfg b/setup.cfg index c62229eee..917dd704b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -211,7 +211,8 @@ universal=1 [tool:pytest] markers = - network: marks tests which require network connection + network: requires network connection + requires_docker: requires running docker [coverage:run] relative_files = True diff --git a/tests/markers.py b/tests/markers.py new file mode 100644 index 000000000..fbe0e0ed8 --- /dev/null +++ b/tests/markers.py @@ -0,0 +1,8 @@ +import pytest + +from moto import settings + +requires_docker = pytest.mark.requires_docker + +if settings.SKIP_REQUIRES_DOCKER: + requires_docker = pytest.mark.skip(reason="running docker required") diff --git a/tests/test_awslambda/test_lambda_eventsourcemapping.py b/tests/test_awslambda/test_lambda_eventsourcemapping.py index b3d2181a0..6f941203c 100644 --- a/tests/test_awslambda/test_lambda_eventsourcemapping.py +++ b/tests/test_awslambda/test_lambda_eventsourcemapping.py @@ -14,6 +14,7 @@ from .utilities import ( wait_for_log_msg, get_test_zip_file_error, ) +from ..markers import requires_docker _lambda_region = "us-west-2" boto3.setup_default_session(region_name=_lambda_region) @@ -54,6 +55,7 @@ def test_create_event_source_mapping(): @mock_logs @mock_lambda @mock_sqs +@requires_docker def test_invoke_function_from_sqs(key): function_name = str(uuid4())[0:6] sqs = boto3.resource("sqs", region_name="us-east-1") @@ -98,6 +100,7 @@ def test_invoke_function_from_sqs(key): @mock_logs @mock_lambda @mock_dynamodb +@requires_docker def test_invoke_function_from_dynamodb_put(): dynamodb = boto3.client("dynamodb", region_name="us-east-1") table_name = str(uuid4())[0:6] + "_table" @@ -149,6 +152,7 @@ def test_invoke_function_from_dynamodb_put(): @mock_logs @mock_lambda @mock_dynamodb +@requires_docker def test_invoke_function_from_dynamodb_update(): dynamodb = boto3.client("dynamodb", region_name="us-east-1") table_name = str(uuid4())[0:6] + "_table" @@ -210,6 +214,7 @@ def test_invoke_function_from_dynamodb_update(): @mock_logs @mock_lambda @mock_sqs +@requires_docker def test_invoke_function_from_sqs_exception(): function_name = str(uuid4())[0:6] logs_conn = boto3.client("logs", region_name="us-east-1") @@ -274,6 +279,7 @@ def test_invoke_function_from_sqs_exception(): @mock_logs @mock_sns @mock_lambda +@requires_docker def test_invoke_function_from_sns(): logs_conn = boto3.client("logs", region_name=_lambda_region) sns_conn = boto3.client("sns", region_name=_lambda_region) diff --git a/tests/test_awslambda/test_lambda_invoke.py b/tests/test_awslambda/test_lambda_invoke.py index 7741f679a..8b981c494 100644 --- a/tests/test_awslambda/test_lambda_invoke.py +++ b/tests/test_awslambda/test_lambda_invoke.py @@ -20,6 +20,7 @@ from .utilities import ( get_lambda_using_network_mode, get_test_zip_largeresponse, ) +from ..markers import requires_docker _lambda_region = "us-west-2" boto3.setup_default_session(region_name=_lambda_region) @@ -27,6 +28,7 @@ boto3.setup_default_session(region_name=_lambda_region) @pytest.mark.network @mock_lambda +@requires_docker def test_invoke_function_that_throws_error(): conn = boto3.client("lambda", _lambda_region) function_name = str(uuid4())[0:6] @@ -61,6 +63,7 @@ def test_invoke_function_that_throws_error(): @pytest.mark.parametrize("invocation_type", [None, "RequestResponse"]) @pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"]) @mock_lambda +@requires_docker def test_invoke_requestresponse_function(invocation_type, key): conn = boto3.client("lambda", _lambda_region) function_name = str(uuid4())[0:6] @@ -118,6 +121,7 @@ def test_invoke_requestresponse_function(invocation_type, key): @pytest.mark.network @mock_lambda +@requires_docker def test_invoke_event_function(): conn = boto3.client("lambda", _lambda_region) function_name = str(uuid4())[0:6] @@ -211,6 +215,7 @@ def test_invoke_lambda_using_networkmode(): @pytest.mark.network @mock_lambda +@requires_docker def test_invoke_function_with_multiple_files_in_zip(): conn = boto3.client("lambda", _lambda_region) function_name = str(uuid4())[0:6] @@ -237,6 +242,7 @@ def test_invoke_function_with_multiple_files_in_zip(): @pytest.mark.network @mock_lambda +@requires_docker def test_invoke_dryrun_function(): conn = boto3.client("lambda", _lambda_region) function_name = str(uuid4())[0:6] @@ -300,6 +306,7 @@ if settings.TEST_SERVER_MODE: @pytest.mark.network @mock_lambda +@requires_docker def test_invoke_lambda_error(): lambda_fx = """ def lambda_handler(event, context): @@ -335,6 +342,7 @@ def lambda_handler(event, context): @pytest.mark.network @pytest.mark.parametrize("key", ["FunctionName", "FunctionArn"]) @mock_lambda +@requires_docker def test_invoke_async_function(key): conn = boto3.client("lambda", _lambda_region) function_name = str(uuid4())[0:6] @@ -360,6 +368,7 @@ def test_invoke_async_function(key): @pytest.mark.network @mock_lambda +@requires_docker def test_invoke_function_large_response(): # AWS Lambda should only return bodies smaller than 6 MB conn = boto3.client("lambda", _lambda_region) diff --git a/tests/test_batch/test_batch_jobs.py b/tests/test_batch/test_batch_jobs.py index 2083cff05..8248aeb99 100644 --- a/tests/test_batch/test_batch_jobs.py +++ b/tests/test_batch/test_batch_jobs.py @@ -8,6 +8,8 @@ import pytest import time from uuid import uuid4 +from ..markers import requires_docker + @mock_logs @mock_ec2 @@ -94,6 +96,7 @@ def test_submit_job_by_name(): @mock_iam @mock_batch @pytest.mark.network +@requires_docker def test_submit_job(): ec2_client, iam_client, _, logs_client, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -158,6 +161,7 @@ def test_submit_job(): @mock_iam @mock_batch @pytest.mark.network +@requires_docker def test_submit_job_multinode(): ec2_client, iam_client, _, logs_client, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -224,6 +228,7 @@ def test_submit_job_multinode(): @mock_iam @mock_batch @pytest.mark.network +@requires_docker def test_list_jobs(): ec2_client, iam_client, _, _, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -290,6 +295,7 @@ def test_list_jobs(): @mock_ecs @mock_iam @mock_batch +@requires_docker def test_terminate_job(): ec2_client, iam_client, _, logs_client, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -396,6 +402,7 @@ def test_cancel_pending_job(): @mock_ecs @mock_iam @mock_batch +@requires_docker def test_cancel_running_job(): """ Test verifies that the moment the job has started, we can't cancel anymore @@ -476,6 +483,7 @@ def _wait_for_job_statuses(client, job_id, statuses, seconds_to_wait=30): @mock_ecs @mock_iam @mock_batch +@requires_docker def test_failed_job(): ec2_client, iam_client, _, _, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -509,6 +517,7 @@ def test_failed_job(): @mock_ecs @mock_iam @mock_batch +@requires_docker def test_dependencies(): ec2_client, iam_client, _, logs_client, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -595,6 +604,7 @@ def retrieve_all_streams(log_stream_name, logs_client): @mock_ecs @mock_iam @mock_batch +@requires_docker def test_failed_dependencies(): ec2_client, iam_client, _, _, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -694,6 +704,7 @@ def test_failed_dependencies(): @mock_ecs @mock_iam @mock_batch +@requires_docker def test_container_overrides(): """ Test if container overrides have any effect. @@ -969,6 +980,7 @@ def test_register_job_definition_with_timeout(): @mock_batch @mock_ec2 @mock_iam +@requires_docker def test_submit_job_with_timeout(): ec2_client, iam_client, _, _, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) @@ -992,6 +1004,7 @@ def test_submit_job_with_timeout(): @mock_batch @mock_ec2 @mock_iam +@requires_docker def test_submit_job_with_timeout_set_at_definition(): ec2_client, iam_client, _, _, batch_client = _get_clients() _, _, _, iam_arn = _setup(ec2_client, iam_client) diff --git a/tests/test_batch_simple/test_batch_jobs.py b/tests/test_batch_simple/test_batch_jobs.py index 03c945dde..76a673b7a 100644 --- a/tests/test_batch_simple/test_batch_jobs.py +++ b/tests/test_batch_simple/test_batch_jobs.py @@ -60,17 +60,17 @@ def test_submit_job_by_name(): job_id = resp["jobId"] resp_jobs = batch_client.describe_jobs(jobs=[job_id]) + assert len(resp_jobs["jobs"]) == 1 - len(resp_jobs["jobs"]).should.equal(1) job = resp_jobs["jobs"][0] - job["jobId"].should.equal(job_id) - job["jobQueue"].should.equal(queue_arn) - job["jobDefinition"].should.equal(job_definition_arn) - job["status"].should.equal("SUCCEEDED") - job.should.contain("container") - job["container"].should.contain("command") - job["container"].should.contain("logStreamName") + assert job["jobId"] == job_id + assert job["jobQueue"] == queue_arn + assert job["jobDefinition"] == job_definition_arn + assert job["status"] == "SUCCEEDED" + assert "container" in job + assert "command" in job["container"] + assert "logStreamName" in job["container"] @mock_batch_simple diff --git a/tests/test_cloudformation/test_cloudformation_custom_resources.py b/tests/test_cloudformation/test_cloudformation_custom_resources.py index 0e0d5ae14..f2d457bfa 100644 --- a/tests/test_cloudformation/test_cloudformation_custom_resources.py +++ b/tests/test_cloudformation/test_cloudformation_custom_resources.py @@ -11,6 +11,7 @@ from unittest import SkipTest from uuid import uuid4 from tests.test_awslambda.utilities import wait_for_log_msg from .fixtures.custom_lambda import get_template, get_template_for_unknown_lambda +from ..markers import requires_docker def get_lambda_code(): @@ -77,6 +78,7 @@ def test_create_custom_lambda_resource(): @mock_lambda @mock_logs @mock_s3 +@requires_docker def test_create_custom_lambda_resource__verify_cfnresponse_failed(): ######### # Integration test using a Custom Resource diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index a284ab101..b0f06e019 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -27,6 +27,7 @@ from moto import ( from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2 +from tests.markers import requires_docker from tests.test_cloudformation.fixtures import fn_join, single_instance_with_ebs_volume @@ -179,6 +180,7 @@ def test_cloudformation_mapping_boto3(): @mock_cloudformation @mock_lambda +@requires_docker def test_lambda_function(): # switch this to python as backend lambda only supports python execution. lambda_code = """ diff --git a/tests/test_core/test_docker.py b/tests/test_core/test_docker.py new file mode 100644 index 000000000..1bf36268d --- /dev/null +++ b/tests/test_core/test_docker.py @@ -0,0 +1,36 @@ +import logging + +import pytest + +from tests.markers import requires_docker + +logger = logging.getLogger(__name__) + + +@requires_docker +@pytest.mark.run(order=0) +def test_docker_package_is_available(): + try: + import docker # noqa: F401 # pylint: disable=unused-import + except ImportError as err: + logger.error("error running docker: %s", err) + assert False, ( + "Docker package cannot be imported. " + + f"This causes various tests to fail. Err: {err}" + ) + + +@requires_docker +@pytest.mark.run(order=0) +def test_docker_is_running_and_available(): + import docker + from docker.errors import DockerException + + try: + docker.from_env() + except DockerException as err: + logger.error("error running docker: %s", err) + assert False, ( + "Docker seems not to be running. " + + f"This causes various tests to fail. Err: {err}" + ) diff --git a/tests/test_events/test_events_lambdatriggers_integration.py b/tests/test_events/test_events_lambdatriggers_integration.py index dd6624086..38ef43441 100644 --- a/tests/test_events/test_events_lambdatriggers_integration.py +++ b/tests/test_events/test_events_lambdatriggers_integration.py @@ -3,6 +3,7 @@ import json from moto import mock_events, mock_iam, mock_lambda, mock_logs, mock_s3 from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID +from ..markers import requires_docker from ..test_awslambda.utilities import get_test_zip_file1, wait_for_log_msg @@ -11,6 +12,7 @@ from ..test_awslambda.utilities import get_test_zip_file1, wait_for_log_msg @mock_lambda @mock_logs @mock_s3 +@requires_docker def test_creating_bucket__invokes_lambda(): iam_client = boto3.client("iam", "us-east-1") lambda_client = boto3.client("lambda", "us-east-1") diff --git a/tests/test_logs/test_integration.py b/tests/test_logs/test_integration.py index ec0bde543..7365bf127 100644 --- a/tests/test_logs/test_integration.py +++ b/tests/test_logs/test_integration.py @@ -13,6 +13,8 @@ from moto import mock_logs, mock_lambda, mock_iam, mock_firehose, mock_s3 from moto.core.utils import unix_time_millis import pytest +from tests.markers import requires_docker + @mock_lambda @mock_logs @@ -100,6 +102,7 @@ def test_put_subscription_filter_update(): @mock_lambda @mock_logs @pytest.mark.network +@requires_docker def test_put_subscription_filter_with_lambda(): # given region_name = "us-east-1" @@ -184,6 +187,7 @@ def test_put_subscription_filter_with_lambda(): @mock_lambda @mock_logs @pytest.mark.network +@requires_docker def test_subscription_filter_applies_to_new_streams(): # given region_name = "us-east-1" diff --git a/tests/test_moto_api/state_manager/test_batch_integration.py b/tests/test_moto_api/state_manager/test_batch_integration.py index 9a182065d..7b4705f92 100644 --- a/tests/test_moto_api/state_manager/test_batch_integration.py +++ b/tests/test_moto_api/state_manager/test_batch_integration.py @@ -1,3 +1,4 @@ +from tests.markers import requires_docker from tests.test_batch import _get_clients, _setup from tests.test_batch.test_batch_jobs import prepare_job, _wait_for_job_status @@ -13,6 +14,7 @@ from unittest import SkipTest @mock_ecs @mock_iam @mock_batch +@requires_docker def test_cancel_pending_job(): if settings.TEST_SERVER_MODE: raise SkipTest("Can't use state_manager in ServerMode directly") diff --git a/tests/test_s3/test_s3_lambda_integration.py b/tests/test_s3/test_s3_lambda_integration.py index a804b0574..c7ba99349 100644 --- a/tests/test_s3/test_s3_lambda_integration.py +++ b/tests/test_s3/test_s3_lambda_integration.py @@ -3,6 +3,7 @@ import json import pytest from moto import mock_lambda, mock_logs, mock_s3, mock_sqs from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID +from tests.markers import requires_docker from tests.test_awslambda.utilities import ( get_test_zip_file_print_event, get_role_name, @@ -26,6 +27,7 @@ REGION_NAME = "us-east-1" (["s3:ObjectCreated:Post", "s3:ObjectCreated:*"], "ObjectCreated:Put"), ], ) +@requires_docker def test_objectcreated_put__invokes_lambda(match_events, actual_event): s3_res = boto3.resource("s3", region_name=REGION_NAME) s3_client = boto3.client("s3", region_name=REGION_NAME) diff --git a/tests/test_secretsmanager/test_server.py b/tests/test_secretsmanager/test_server.py index 0f8e31bb8..bf7136615 100644 --- a/tests/test_secretsmanager/test_server.py +++ b/tests/test_secretsmanager/test_server.py @@ -7,6 +7,7 @@ import sure # noqa # pylint: disable=unused-import import moto.server as server from moto import mock_secretsmanager, mock_lambda, mock_iam, mock_logs, settings +from tests.markers import requires_docker from tests.test_awslambda.test_lambda import get_test_zip_file1 DEFAULT_SECRET_NAME = "test-secret" @@ -456,6 +457,7 @@ if not settings.TEST_SERVER_MODE: @mock_lambda @mock_logs @mock_secretsmanager + @requires_docker def test_rotate_secret_lambda_invocations(): conn = boto3.client("iam", region_name="us-east-1") logs_conn = boto3.client("logs", region_name="us-east-1") diff --git a/tests/test_sqs/test_sqs_integration.py b/tests/test_sqs/test_sqs_integration.py index 3aded4216..1e89f7137 100644 --- a/tests/test_sqs/test_sqs_integration.py +++ b/tests/test_sqs/test_sqs_integration.py @@ -4,6 +4,7 @@ import time import uuid from moto import mock_lambda, mock_sqs, mock_logs +from tests.markers import requires_docker from tests.test_awslambda.test_lambda import get_test_zip_file1, get_role_name from tests.test_awslambda.utilities import get_test_zip_file_print_event @@ -11,6 +12,7 @@ from tests.test_awslambda.utilities import get_test_zip_file_print_event @mock_logs @mock_lambda @mock_sqs +@requires_docker def test_invoke_function_from_sqs_queue(): logs_conn = boto3.client("logs", region_name="us-east-1") sqs = boto3.resource("sqs", region_name="us-east-1") @@ -71,6 +73,7 @@ def test_invoke_function_from_sqs_queue(): @mock_logs @mock_lambda @mock_sqs +@requires_docker def test_invoke_function_from_sqs_fifo_queue(): """ Create a FIFO Queue