Best Python code snippet using localstack_python
test_register_service.py
Source:test_register_service.py  
1import sys2import json3import datetime4import unittest5from contextlib import ExitStack6from unittest import mock7from unittest.mock import MagicMock8import mimesis9from deploy2ecscli.app import App10class TestRegisterService(unittest.TestCase):11    DEFAULT_YAML = """12    integration:13        images:14        task_definitions: 15        services:16            -   name: example_application17                cluster: ecs-cluster18                task_family: example_application19                template: ./config/application.yaml20                bind_variables:21                    -   name: ACCOUNT_ID22                        value: 9999999923                before_deploy:24                    tasks:25                        -   task_family: migrate26                            cluster: ecs-cluster27                            template: ./config/migrate.yaml28    """29    TEMPLATE_SERVICE_YAML = """30    cluster: !Ref CLUSTER_NAME31    serviceName: !Ref SERVICE_NAME32    taskDefinition: !Ref TASK_DEFINITION_ARN33    loadBalancers:34        - containerPort: 8035          containerName: nginx36          targetGroupArn: !Ref TARGET_GROUP_ARN37    desiredCount: 238    launchType: FARGATE39    platformVersion: LATEST40    deploymentConfiguration:41    minimumHealthyPercent: 10042    maximumPercent: 20043    networkConfiguration:44    awsvpcConfiguration:45        securityGroups: !Split46            - ","47            - !Ref SECURITY_GROUPS48        subnets: !Split49            - ","50            - !Ref SUBNETS51        assignPublicIp: ENABLED52    healthCheckGracePeriodSeconds: 053    schedulingStrategy: REPLICA54    enableECSManagedTags: false55    tags:56        - key: JSON_COMMIT_HASH57          value: !Ref JSON_COMMIT_HASH58    """59    TEMPLATE_ONETIME_TASK_YAML = """60    cluster: !Ref CLUSTER_NAME61    taskDefinition: !Ref TASK_DEFINITION_ARN62    launchType: FARGATE63    platformVersion: LATEST64    networkConfiguration:65    awsvpcConfiguration:66        securityGroups: !Split67            - ","68            - !Ref SECURITY_GROUPS69        subnets: !Split70            - ","71            - !Ref SUBNETS72        assignPublicIp: ENABLED73    """74    TEMPLATE_MAPPING = {75        './config/application.yaml': TEMPLATE_SERVICE_YAML,76        './config/migrate.yaml': TEMPLATE_ONETIME_TASK_YAML77    }78    RESPONSE_SERVICES_TEMPLATE = """{79        "services": [80            {81                "serviceArn": "arn:aws:ecs:REGION:ACCOUNT_ID:service/ecs-cluster/example_application",82                "serviceName": "example_application",83                "clusterArn": "arn:aws:ecs:REGION:ACCOUNT_ID:cluster/ecs-cluster",84                "loadBalancers": [85                    {86                        "targetGroupArn": "arn:aws:elasticloadbalancing:REGION:ACCOUNT_ID:targetgroup/ecs-cluster/xxxxXXXXxxxxXXXX",87                        "containerName": "nginx",88                        "containerPort": 8089                    }90                ],91                "serviceRegistries": [],92                "status": "{{status}}",93                "desiredCount": 2,94                "runningCount": 2,95                "pendingCount": 0,96                "launchType": "FARGATE",97                "platformVersion": "LATEST",98                "taskDefinition": "arn:aws:ecs:REGION:ACCOUNT_ID:task-definition/example_application:{{revision}}",99                "deploymentConfiguration": {100                    "maximumPercent": 200,101                    "minimumHealthyPercent": 100102                },103                "deployments": [104                    {105                        "id": "ecs-svc/9999999999999999999",106                        "status": "PRIMARY",107                        "taskDefinition": "arn:aws:ecs:REGION:ACCOUNT_ID:task-definition/example_application:{{revision}}",108                        "desiredCount": 2,109                        "pendingCount": 0,110                        "runningCount": 2,111                        "createdAt": "2019-10-25T20:41:04.312000+09:00",112                        "updatedAt": "2019-10-25T20:44:57.843000+09:00",113                        "launchType": "FARGATE",114                        "platformVersion": "1.3.0",115                        "networkConfiguration": {116                            "awsvpcConfiguration": {117                                "subnets": [118                                    "subnet-xxxxxxx1",119                                    "subnet-xxxxxxx2",120                                    "subnet-xxxxxxx3"121                                ],122                                "securityGroups": [123                                    "sg-xxxxxxxx"124                                ],125                                "assignPublicIp": "ENABLED"126                            }127                        }128                    }129                ],130                "roleArn": "arn:aws:iam::ACCOUNT_ID:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS",131                "createdAt": "2019-10-24T13:30:06.215000+09:00",132                "placementConstraints": [],133                "placementStrategy": [],134                "networkConfiguration": {135                    "awsvpcConfiguration": {136                        "subnets": [137                            "subnet-xxxxxxx1",138                            "subnet-xxxxxxx2",139                            "subnet-xxxxxxx3"140                        ],141                        "securityGroups": [142                            "sg-xxxxxxxx"143                        ],144                        "assignPublicIp": "ENABLED"145                    }146                },147                "healthCheckGracePeriodSeconds": 0,148                "schedulingStrategy": "REPLICA",149                "enableECSManagedTags": false,150                "propagateTags": "NONE",151                "tags": [152                    {153                        "key": "JSON_COMMIT_HASH",154                        "value": "{{json_commit_hash}}"155                    }156                ]157            }158        ],159        "failures": [],160        "ResponseMetadata": {161            "RequestId": "8022c17e-9865-43dc-80bd-f87eaa11e7bc",162            "HTTPStatusCode": 200,163            "HTTPHeaders": {164                "x-amzn-requestid": "8022c17e-9865-43dc-80bd-f87eaa11e7bc",165                "content-type": "application/x-amz-json-1.1",166                "content-length": "20872",167                "date": "Wed, 30 Oct 2019 11:57:06 GMT"168            },169            "RetryAttempts": 0170        }171    }172    """173    RESPONSE_TASK_DEFINITION_TEMPLATE = """{174        "taskDefinition": {175            "taskDefinitionArn": "arn:aws:ecs:REGION:ACCOUNT_ID:task-definition/example_application:{{revision}}",176            "containerDefinitions": [177                {178                    "name": "nginx",179                    "image": "ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/example_application/nginx:1",180                    "cpu": 0,181                    "portMappings": [182                        {183                            "containerPort": 80,184                            "hostPort": 80,185                            "protocol": "tcp"186                        }187                    ],188                    "essential": true,189                    "mountPoints": [],190                    "volumesFrom": [191                        {192                            "sourceContainer": "app",193                            "readOnly": true194                        }195                    ],196                    "dependsOn": [197                        {198                            "containerName": "app",199                            "condition": "HEALTHY"200                        }201                    ],202                    "logConfiguration": {203                        "logDriver": "awslogs",204                        "options": {205                            "awslogs-group": "/ecs/example_application",206                            "awslogs-region": "REGION",207                            "awslogs-stream-prefix": "ecs"208                        }209                    },210                    "healthCheck": {211                        "command": [212                            "CMD-SHELL",213                            "wget -q -O /dev/null http://localhost/healthcheck || exit 1"214                        ],215                        "interval": 5,216                        "timeout": 5,217                        "retries": 5,218                        "startPeriod": 10219                    }220                },221                {222                    "name": "app",223                    "image": "ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/example_application/app:1",224                    "cpu": 0,225                    "memoryReservation": 500,226                    "portMappings": [],227                    "essential": true,228                    "mountPoints": [],229                    "volumesFrom": [],230                    "logConfiguration": {231                        "logDriver": "awslogs",232                        "options": {233                            "awslogs-group": "/ecs/example_application",234                            "awslogs-region": "REGION",235                            "awslogs-stream-prefix": "ecs"236                        }237                    },238                    "healthCheck": {239                        "command": [240                            "CMD-SHELL",241                            "ls /var/run/app/puma.sock || exit 1"242                        ],243                        "interval": 5,244                        "timeout": 5,245                        "retries": 5,246                        "startPeriod": 10247                    }248                }249            ],250            "family": "example_application",251            "taskRoleArn": "arn:aws:iam::ACCOUNT_ID:role/ecsTaskExecutionRole",252            "executionRoleArn": "arn:aws:iam::ACCOUNT_ID:role/ecsTaskExecutionRole",253            "networkMode": "awsvpc",254            "revision": 1,255            "volumes": [],256            "status": "ACTIVE",257            "placementConstraints": [],258            "compatibilities": [259                "EC2",260                "FARGATE"261            ],262            "requiresCompatibilities": [263                "FARGATE"264            ],265            "cpu": "512",266            "memory": "1024"267        },268        "tags": [269            {270                "key": "JSON_COMMIT_HASH",271                "value": "{{json_commit_hash}}"272            }273        ],274        "ResponseMetadata": {275            "RequestId": "1c418748-b05f-4d3d-88df-0dcf5d414c03",276            "HTTPStatusCode": 200,277            "HTTPHeaders": {278                "x-amzn-requestid": "1c418748-b05f-4d3d-88df-0dcf5d414c03",279                "content-type": "application/x-amz-json-1.1",280                "content-length": "2877",281                "date": "Wed, 30 Oct 2019 12:15:52 GMT"282            },283            "RetryAttempts": 0284        }285    }286    """287    def __subprocer_run(self, command):288        if command.startswith('git rev-parse --is-inside-work-tree'):289            return MagicMock(returncode=0, stdout=b'true')290        if command.startswith('git --no-pager name-rev --name-only HEAD'):291            return MagicMock(returncode=0, stdout=b'integration')292        if command.startswith('git --no-pager log -n 1 --pretty=oneline'):293            stdout = '{0} {1}'294            stdout = stdout.format(295                mimesis.Cryptographic().token_hex(),296                mimesis.Text().sentence())297            return MagicMock(returncode=0, stdout=stdout.encode('utf8'))298        if command.startswith('git --no-pager log -n 1'):299            stdout = '{0} {1}'300            stdout = stdout.format(301                mimesis.Cryptographic().token_hex(),302                mimesis.Text().sentence())303            return MagicMock(returncode=0, stdout=stdout.encode('utf8'))304        return MagicMock(returncode=127, stderr=b'command not found')305    def test_when_service_inactive(self):306        with ExitStack() as stack:307            params = [308                'deploy2ecs',309                'register-service',310                '--config', mimesis.File().file_name(),311                '-q'312            ]313            stack.enter_context(mock.patch.object(sys, 'argv', params))314            describe_services = \315                self.RESPONSE_SERVICES_TEMPLATE \316                    .replace('{', '{{') \317                    .replace('}', '}}') \318                    .replace('{{{{', '{') \319                    .replace('}}}}', '}') \320                    .format(321                        status='INACTIVE',322                        revision=100,323                        json_commit_hash=mimesis.Cryptographic().token_hex()324                    )325            describe_services = json.loads(describe_services)326            mock_aws = stack.enter_context(mock.patch('boto3.client'))327            mock_aws = mock_aws.return_value328            mock_aws.describe_services.return_value = \329                describe_services330            mock_aws.describe_tasks.return_value = {331                'tasks': [332                    {333                        'taskArn': mimesis.Cryptographic.token_hex(),334                        'lastStatus': 'STOPPED',335                        'containers': [336                            {'name': mimesis.File().file_name(), 'exitCode': 0}337                        ]338                    }339                ],340                'failures': []341            }342            mock_aws.de343            mock_subprocer = \344                stack.enter_context(mock.patch('subprocess.run'))345            mock_subprocer.side_effect = \346                lambda x, **_: self.__subprocer_run(x)347            stack.enter_context(mock.patch(348                'deploy2ecscli.app.open', mock.mock_open(read_data=self.DEFAULT_YAML)))349            config_open = MagicMock()350            config_open.side_effect = \351                lambda x: mock.mock_open(352                    read_data=(self.TEMPLATE_MAPPING[x]))\353                .return_value354            stack.enter_context(mock.patch(355                'deploy2ecscli.config.open', config_open))356            App().run()357            mock_aws.run_task.assert_called()358            mock_aws.create_service.assert_called()359            mock_aws.update_service.assert_not_called()360            mock_aws.tag_resource.assert_not_called()361    def test_when_unmatch_task_definition_revision(self):362        with ExitStack() as stack:363            params = [364                'deploy2ecs',365                'register-service',366                '--config', mimesis.File().file_name(),367                '-q'368            ]369            stack.enter_context(mock.patch.object(sys, 'argv', params))370            describe_task_definition = \371                self.RESPONSE_TASK_DEFINITION_TEMPLATE \372                    .replace('{', '{{') \373                    .replace('}', '}}') \374                    .replace('{{{{', '{') \375                    .replace('}}}}', '}') \376                    .format(377                        revision=101,378                        json_commit_hash=mimesis.Cryptographic().token_hex()379                    )380            describe_task_definition = json.loads(describe_task_definition)381            describe_services = \382                self.RESPONSE_SERVICES_TEMPLATE \383                    .replace('{', '{{') \384                    .replace('}', '}}') \385                    .replace('{{{{', '{') \386                    .replace('}}}}', '}') \387                    .format(388                        status='ACTIVE',389                        revision=100,390                        json_commit_hash=mimesis.Cryptographic().token_hex()391                    )392            describe_services = json.loads(describe_services)393            mock_aws = stack.enter_context(mock.patch('boto3.client'))394            mock_aws = mock_aws.return_value395            mock_aws.describe_services.return_value = \396                describe_services397            mock_aws.describe_task_definition.return_value = \398                describe_task_definition399            mock_aws.describe_tasks.return_value = {400                'tasks': [401                    {402                        'taskArn': mimesis.Cryptographic.token_hex(),403                        'lastStatus': 'STOPPED',404                        'containers': [405                            {'name': mimesis.File().file_name(), 'exitCode': 0}406                        ]407                    }408                ],409                'failures': []410            }411            mock_subprocer = \412                stack.enter_context(mock.patch('subprocess.run'))413            mock_subprocer.side_effect = \414                lambda x, **_: self.__subprocer_run(x)415            stack.enter_context(mock.patch(416                'deploy2ecscli.app.open', mock.mock_open(read_data=self.DEFAULT_YAML)))417            config_open = MagicMock()418            config_open.side_effect = \419                lambda x: mock.mock_open(420                    read_data=(self.TEMPLATE_MAPPING[x]))\421                .return_value422            stack.enter_context(mock.patch(423                'deploy2ecscli.config.open', config_open))424            App().run()425            mock_aws.run_task.assert_called()426            mock_aws.create_service.assert_not_called()427            mock_aws.update_service.assert_called()428            mock_aws.tag_resource.assert_called()429    def test_when_json_commit_hash_empty(self):430        with ExitStack() as stack:431            params = [432                'deploy2ecs',433                'register-service',434                '--config', mimesis.File().file_name(),435                '-q'436            ]437            stack.enter_context(mock.patch.object(sys, 'argv', params))438            describe_task_definition = \439                self.RESPONSE_TASK_DEFINITION_TEMPLATE \440                    .replace('{', '{{') \441                    .replace('}', '}}') \442                    .replace('{{{{', '{') \443                    .replace('}}}}', '}') \444                    .format(445                        revision=100,446                        json_commit_hash=mimesis.Cryptographic().token_hex()447                    )448            describe_task_definition = json.loads(describe_task_definition)449            describe_services = \450                self.RESPONSE_SERVICES_TEMPLATE \451                    .replace('{', '{{') \452                    .replace('}', '}}') \453                    .replace('{{{{', '{') \454                    .replace('}}}}', '}') \455                    .format(456                        status='ACTIVE',457                        revision=100,458                        json_commit_hash='')459            describe_services = json.loads(describe_services)460            mock_aws = stack.enter_context(mock.patch('boto3.client'))461            mock_aws = mock_aws.return_value462            mock_aws.describe_services.return_value = \463                describe_services464            mock_aws.describe_task_definition.return_value = \465                describe_task_definition466            mock_aws.run_task.return_value = {467                'tasks': [468                    {469                        'taskArn': mimesis.Cryptographic.token_hex(),470                        'lastStatus': 'STOPPED',471                        'containers': [472                            {'name': mimesis.File().file_name(), 'exitCode': 0}473                        ]474                    }475                ],476                'failures': []477            }478            mock_aws.describe_tasks.return_value = {479                'tasks': [480                    {481                        'taskArn': mimesis.Cryptographic.token_hex(),482                        'lastStatus': 'STOPPED',483                        'containers': [484                            {'name': mimesis.File().file_name(), 'exitCode': 0}485                        ]486                    }487                ],488                'failures': []489            }490            mock_subprocer = \491                stack.enter_context(mock.patch('subprocess.run'))492            mock_subprocer.side_effect = \493                lambda x, **_: self.__subprocer_run(x)494            stack.enter_context(mock.patch(495                'deploy2ecscli.app.open', mock.mock_open(read_data=self.DEFAULT_YAML)))496            config_open = MagicMock()497            config_open.side_effect = \498                lambda x: mock.mock_open(499                    read_data=(self.TEMPLATE_MAPPING[x]))\500                .return_value501            stack.enter_context(mock.patch(502                'deploy2ecscli.config.open', config_open))503            App().run()504            mock_aws.run_task.assert_called()505            mock_aws.create_service.assert_not_called()506            mock_aws.update_service.assert_called()507            mock_aws.tag_resource.assert_called()508    def test_when_unmatch_json_commit_hash(self):509        with ExitStack() as stack:510            params = [511                'deploy2ecs',512                'register-service',513                '--config', mimesis.File().file_name(),514                '-q'515            ]516            stack.enter_context(mock.patch.object(sys, 'argv', params))517            describe_task_definition = \518                self.RESPONSE_TASK_DEFINITION_TEMPLATE \519                    .replace('{', '{{') \520                    .replace('}', '}}') \521                    .replace('{{{{', '{') \522                    .replace('}}}}', '}') \523                    .format(524                        revision=100,525                        json_commit_hash=mimesis.Cryptographic().token_hex()526                    )527            describe_task_definition = json.loads(describe_task_definition)528            describe_services = \529                self.RESPONSE_SERVICES_TEMPLATE \530                    .replace('{', '{{') \531                    .replace('}', '}}') \532                    .replace('{{{{', '{') \533                    .replace('}}}}', '}') \534                    .format(535                        status='ACTIVE',536                        revision=100,537                        json_commit_hash=mimesis.Cryptographic().token_hex()538                    )539            describe_services = json.loads(describe_services)540            mock_aws = stack.enter_context(mock.patch('boto3.client'))541            mock_aws = mock_aws.return_value542            mock_aws.describe_services.return_value = \543                describe_services544            mock_aws.describe_task_definition.return_value = \545                describe_task_definition546            mock_aws.run_task.return_value = {547                'tasks': [548                    {549                        'taskArn': mimesis.Cryptographic.token_hex(),550                        'lastStatus': 'STOPPED',551                        'containers': [552                            {'name': mimesis.File().file_name(), 'exitCode': 0}553                        ]554                    }555                ],556                'failures': []557            }558            mock_aws.describe_tasks.return_value = {559                'tasks': [560                    {561                        'taskArn': mimesis.Cryptographic.token_hex(),562                        'lastStatus': 'STOPPED',563                        'containers': [564                            {'name': mimesis.File().file_name(), 'exitCode': 0}565                        ]566                    }567                ],568                'failures': []569            }570            mock_subprocer = \571                stack.enter_context(mock.patch('subprocess.run'))572            mock_subprocer.side_effect = \573                lambda x, **_: self.__subprocer_run(x)574            stack.enter_context(mock.patch(575                'deploy2ecscli.app.open', mock.mock_open(read_data=self.DEFAULT_YAML)))576            config_open = MagicMock()577            config_open.side_effect = \578                lambda x: mock.mock_open(579                    read_data=(self.TEMPLATE_MAPPING[x]))\580                .return_value581            stack.enter_context(mock.patch(582                'deploy2ecscli.config.open', config_open))583            App().run()584            mock_aws.run_task.assert_called()585            mock_aws.create_service.assert_not_called()586            mock_aws.update_service.assert_called()...ecs_utils_test.py
Source:ecs_utils_test.py  
1"""Test case for ecs_utils."""2import copy3import datetime4import unittest5from unittest import TestCase6from unittest.mock import patch7import scripts.ecs_utils as ecs_utils8# speed up the polling9ecs_utils.SLEEP_TIME_S = 010# note: we override time.time()11POLL_S = 1012GOOD_SERVICE = {13    'services': [{14        'serviceName': 'service-foo',15        'runningCount': 2,16        'desiredCount': 2,17        'deployments': [{18            'runningCount': 2,19            'desiredCount': 2,20            'status': 'PRIMARY',21            'rolloutState': 'COMPLETED',22            'createdAt': datetime.time()23        }]24    }]25}26INPROGRESS_SERVICE = copy.deepcopy(GOOD_SERVICE)27INPROGRESS_SERVICE['services'][0]['deployments'][0]['rolloutState'] = 'IN_PROGRESS'28BAD_SERVICE = copy.deepcopy(GOOD_SERVICE)29BAD_SERVICE['services'][0]['deployments'][0]['status'] = 'BAD'30BAD_SERVICE['services'][0]['deployments'][0]['rolloutState'] = 'BAD'31BAD_SERVICE['services'][0]['runningCount'] = 132INACTIVE_SERVICE = copy.deepcopy(GOOD_SERVICE)33INACTIVE_SERVICE['services'][0]['desiredCount'] = 034INACTIVE_SERVICE['services'][0]['runningCount'] = 0 35BAD_TASKS = {'tasks': [36    {'healthStatus': 'HEALTHY', 'taskArn': 'foo'},37    {'healthStatus': 'UNHEALTHY', 'taskArn': 'bar'}38]}39GOOD_TASKS = {'tasks': [40    {'healthStatus': 'HEALTHY', 'taskArn': 'foo'},41    {'healthStatus': 'HEALTHY', 'taskArn': 'bar'}42]}43TASKS = {44    'taskArns': ['foo', 'bar'],45    'nextoken': None46}47EMPTY_TASKS = copy.deepcopy(TASKS)48EMPTY_TASKS['taskArns'] = []49class EcsTestCase(TestCase):50    """Test the ecs utils module."""51    def setUp(self):52        # time will advance by 1sec every polling iteration53        self.patcher = patch('time.time')54        self.mock_time = self.patcher.start()55        self.mock_time.side_effect = list(range(100))56        self.addCleanup(self.patcher.stop)57    @patch('boto3.client')58    def test_poll_cluster_positive(self, mock_boto):59        mock_client = mock_boto.return_value60        mock_client.describe_services.return_value = GOOD_SERVICE61        mock_client.list_tasks.return_value = TASKS62        mock_client.describe_tasks.return_value = GOOD_TASKS63        ecs_utils.poll_cluster_state(mock_client, 'cluster-foo', ['service-foo'], POLL_S)64    @patch('boto3.client')65    def test_poll_cluster_new_arn(self, mock_boto):66        mock_client = mock_boto.return_value67        mock_client.describe_services.return_value = GOOD_SERVICE68        mock_client.list_tasks.return_value = TASKS69        mock_client.describe_tasks.return_value = GOOD_TASKS70        ecs_utils.poll_cluster_state(mock_client, 'cluster-foo', ['cluster-foo/service-foo'], POLL_S)71    @patch('boto3.client')72    def test_poll_cluster_matching_cluster_and_service_name(self, mock_boto):73        mock_client = mock_boto.return_value74        mock_client.describe_services.return_value = GOOD_SERVICE75        mock_client.list_tasks.return_value = TASKS76        mock_client.describe_tasks.return_value = GOOD_TASKS77        ecs_utils.poll_cluster_state(mock_client, 'service-foo', ['service-foo'], POLL_S)78    @patch('boto3.client')79    def test_poll_cluster_with_inactive_service(self, mock_boto):80        mock_client = mock_boto.return_value81        mock_client.describe_services.return_value = INACTIVE_SERVICE82        mock_client.list_tasks.return_value = EMPTY_TASKS83        mock_client.describe_tasks.side_effect = Exception('Tasks cannot be empty.')84        ecs_utils.poll_cluster_state(mock_client, 'cluster-foo', ['service-foo'], POLL_S)85    @patch('scripts.ecs_utils.print_events')86    @patch('boto3.client')87    def test_poll_cluster_timeout(self, mock_boto, mock_print_events):88        mock_client = mock_boto.return_value89        mock_client.describe_services.return_value = BAD_SERVICE90        with self.assertRaises(ecs_utils.TimeoutException):91            ecs_utils.poll_cluster_state(mock_client, 'cluster-foo', ['service-foo'], POLL_S)92    @patch('scripts.ecs_utils.print_events')93    @patch('boto3.client')94    def test_poll_cluster_bad_tasks(self, mock_boto, mock_print_events):95        mock_client = mock_boto.return_value96        mock_client.describe_services.return_value = GOOD_SERVICE97        mock_client.list_tasks.return_value = TASKS98        mock_client.describe_tasks.return_value = BAD_TASKS99        with self.assertRaises(ecs_utils.TimeoutException):100            ecs_utils.poll_cluster_state(mock_client, 'cluster-foo', ['service-foo'], POLL_S)101    @patch('scripts.ecs_utils.print_events')102    @patch('boto3.client')103    def test_poll_deployment_positive(self, mock_boto, mock_print_events):104        mock_client = mock_boto.return_value105        mock_client.describe_services.return_value = GOOD_SERVICE106        mock_client.list_tasks.return_value = TASKS107        mock_client.describe_tasks.side_effect = [BAD_TASKS, GOOD_TASKS]108        ecs_utils.poll_deployment_state(mock_client, 'cluster-foo', 'service-foo', POLL_S)109    @patch('scripts.ecs_utils.print_events')110    @patch('boto3.client')111    def test_poll_deployment_in_progres_timeout(self, mock_boto, mock_print_events):112        mock_client = mock_boto.return_value113        mock_client.describe_services.return_value = INPROGRESS_SERVICE114        with self.assertRaises(ecs_utils.TimeoutException):115            ecs_utils.poll_deployment_state(mock_client, 'cluster-foo', ['service-foo'], POLL_S)116    @patch('scripts.ecs_utils.print_events')117    @patch('boto3.client')118    def test_poll_deployment_bad_deploy(self, mock_boto, mock_print_events):119        mock_client = mock_boto.return_value120        mock_client.describe_services.return_value = BAD_SERVICE121        mock_client.list_tasks.return_value = TASKS122        with self.assertRaises(ecs_utils.TimeoutException):123            ecs_utils.poll_deployment_state(mock_client, 'cluster-foo', 'service-foo', POLL_S)124    @patch('scripts.ecs_utils.print_events')125    @patch('boto3.client')126    def test_poll_deployment_bad_tasks(self, mock_boto, mock_print_events):127        mock_client = mock_boto.return_value128        mock_client.describe_services.return_value = GOOD_SERVICE129        mock_client.list_tasks.return_value = TASKS130        mock_client.describe_tasks.side_effect = [BAD_TASKS] * 50131        with self.assertRaises(ecs_utils.TimeoutException):...test_ecs_probes.py
Source:test_ecs_probes.py  
1from unittest.mock import MagicMock, patch2import pytest3from chaoslib.exceptions import FailedActivity4from chaosaws.ecs.probes import (5    are_all_desired_tasks_running,6    describe_cluster,7    describe_service,8    describe_tasks,9    service_is_deploying,10)11@patch("chaosaws.ecs.probes.aws_client", autospec=True)12def test_ecs_service_is_not_deploying(aws_client):13    client = MagicMock()14    client.describe_services = MagicMock(15        return_value={"services": [{"deployments": [{"status": "PRIMARY"}]}]}16    )17    aws_client.return_value = client18    cluster = "ecs-cluster"19    service = "ecs-service"20    response = service_is_deploying(cluster, service)21    client.describe_services.assert_called_with(cluster=cluster, services=[service])22    assert response is False23@patch("chaosaws.ecs.probes.aws_client", autospec=True)24def test_ecs_service_is_deploying(aws_client):25    client = MagicMock()26    client.describe_services = MagicMock(27        return_value={28            "services": [{"deployments": [{"status": "PRIMARY"}, {"status": "ACTIVE"}]}]29        }30    )31    aws_client.return_value = client32    cluster = "ecs-cluster"33    service = "ecs-service"34    response = service_is_deploying(cluster, service)35    client.describe_services.assert_called_with(cluster=cluster, services=[service])36    assert response is True37@patch("chaosaws.ecs.probes.aws_client", autospec=True)38def test_error_checking_ecs_service_is_not_deploying(aws_client):39    client = MagicMock()40    client.describe_services = MagicMock(41        return_value={42            "services": [],43            "failures": [{"reason": "some_reason", "arn": "some_arn"}],44        }45    )46    aws_client.return_value = client47    cluster = "ecs-cluster"48    service = "ecs-service"49    with pytest.raises(FailedActivity) as exceptionInfo:50        service_is_deploying(cluster, service)51    client.describe_services.assert_called_with(cluster=cluster, services=[service])52    assert "Error retrieving service data from AWS" in str(exceptionInfo.value)53@patch("chaosaws.ecs.probes.aws_client", autospec=True)54def test_are_all_tasks_running_true(aws_client):55    client = MagicMock()56    client.describe_services = MagicMock(57        return_value={58            "services": [59                {60                    "serviceName": "MyGenericService",61                    "desiredCount": 3,62                    "runningCount": 3,63                }64            ]65        }66    )67    aws_client.return_value = client68    cluster = "ecs-cluster"69    service = "MyGenericService"70    response = are_all_desired_tasks_running(cluster, service)71    client.describe_services.assert_called_with(cluster=cluster, services=[service])72    assert response73@patch("chaosaws.ecs.probes.aws_client", autospec=True)74def test_are_all_tasks_running_false(aws_client):75    client = MagicMock()76    client.describe_services = MagicMock(77        return_value={78            "services": [79                {80                    "serviceName": "MyGenericService",81                    "desiredCount": 3,82                    "runningCount": 2,83                }84            ]85        }86    )87    aws_client.return_value = client88    cluster = "ecs-cluster"89    service = "MyGenericService"90    response = are_all_desired_tasks_running(cluster, service)91    client.describe_services.assert_called_with(cluster=cluster, services=[service])92    assert not response93@patch("chaosaws.ecs.probes.aws_client", autospec=True)94def test_are_all_tasks_running_exception(aws_client):95    client = MagicMock()96    client.describe_services = MagicMock(return_value={"services": []})97    aws_client.return_value = client98    cluster = "ecs-cluster"99    service = "MyGenericService"100    with pytest.raises(FailedActivity) as e:101        are_all_desired_tasks_running(cluster, service)102    client.describe_services.assert_called_with(cluster=cluster, services=[service])103    assert "Error retrieving service data from AWS" in str(e.value)104@patch("chaosaws.ecs.probes.aws_client", autospec=True)105def test_describe_clusters(aws_client):106    client = MagicMock()107    aws_client.return_value = client108    client.describe_clusters.return_value = {109        "clusters": [110            {111                "clusterArn": "arn:aws:ecs:region:012345678910:cluster/MyCluster",112                "clusterName": "MyCluster",113                "status": "ACTIVE",114            }115        ]116    }117    response = describe_cluster(cluster="MyCluster")118    client.describe_clusters.assert_called_with(clusters=["MyCluster"])119    assert response["clusters"][0]["clusterName"] == "MyCluster"120@patch("chaosaws.ecs.probes.aws_client", autospec=True)121def test_describe_service(aws_client):122    client = MagicMock()123    aws_client.return_value = client124    client.describe_services.return_value = {125        "services": [126            {127                "clusterArn": "arn:aws:ecs:region:012345678910:cluster/MyCluster",128                "serviceArn": "arn:aws:ecs:region:012345678910:service/MyService",129                "serviceName": "MyService",130                "status": "ACTIVE",131            }132        ]133    }134    response = describe_service(cluster="MyCluster", service="MyService")135    client.describe_services.assert_called_with(136        cluster="MyCluster", services=["MyService"]137    )138    assert response["services"][0]["serviceName"] == "MyService"139@patch("chaosaws.ecs.probes.aws_client", autospec=True)140def test_describe_tasks(aws_client):141    client = MagicMock()142    aws_client.return_value = client143    client.get_paginator.return_value.paginate.return_value = [144        {"taskArns": ["arn:aws:ecs:region:012345678910:task/MyCluster/123456789"]}145    ]146    client.describe_tasks.return_value = {147        "tasks": [148            {149                "clusterArn": "arn:aws:ecs:region:012345678910:cluster/" "MyCluster",150                "taskArn": "arn:aws:ecs:region:012345678910:task/MyCluster/"151                "123456789",152                "version": 22,153            }154        ]155    }156    response = describe_tasks(cluster="MyCluster")157    client.get_paginator.return_value.paginate.assert_called_with(cluster="MyCluster")158    client.describe_tasks.assert_called_with(159        cluster="MyCluster",160        tasks=["arn:aws:ecs:region:012345678910:task/MyCluster/123456789"],161    )...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
