From 5c4b68c5ea0b22862e593a3ae85571902f2ff778 Mon Sep 17 00:00:00 2001 From: William Richard Date: Sun, 31 Jan 2021 05:09:52 -0500 Subject: [PATCH] Add support for the force argument for ecs.delete_service (#3631) This argument allows you to delete a service even when its DesiredCount is non-zero. https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html#ECS.Client.delete_service --- moto/ecs/models.py | 4 +-- moto/ecs/responses.py | 3 +- tests/test_ecs/test_ecs_boto3.py | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/moto/ecs/models.py b/moto/ecs/models.py index e0efb3414..ad09dcef8 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -1147,14 +1147,14 @@ class EC2ContainerServiceBackend(BaseBackend): else: raise ServiceNotFoundException - def delete_service(self, cluster_name, service_name): + def delete_service(self, cluster_name, service_name, force): cluster_service_pair = "{0}:{1}".format(cluster_name, service_name) if cluster_name not in self.clusters: raise ClusterNotFoundException if cluster_service_pair in self.services: service = self.services[cluster_service_pair] - if service.desired_count > 0: + if service.desired_count > 0 and not force: raise InvalidParameterException( "The service cannot be stopped while it is scaled above 0." ) diff --git a/moto/ecs/responses.py b/moto/ecs/responses.py index 9e6cb182e..9263d2074 100644 --- a/moto/ecs/responses.py +++ b/moto/ecs/responses.py @@ -226,7 +226,8 @@ class EC2ContainerServiceResponse(BaseResponse): def delete_service(self): service_name = self._get_param("service") cluster_name = self._get_param("cluster", "default") - service = self.ecs_backend.delete_service(cluster_name, service_name) + force = self._get_param("force", False) + service = self.ecs_backend.delete_service(cluster_name, service_name, force) return json.dumps({"service": service.response_object}) def register_container_instance(self): diff --git a/tests/test_ecs/test_ecs_boto3.py b/tests/test_ecs/test_ecs_boto3.py index 941664cc2..3556c96e4 100644 --- a/tests/test_ecs/test_ecs_boto3.py +++ b/tests/test_ecs/test_ecs_boto3.py @@ -890,6 +890,53 @@ def test_delete_service(): ) +@mock_ecs +def test_delete_service_force(): + client = boto3.client("ecs", region_name="us-east-1") + _ = client.create_cluster(clusterName="test_ecs_cluster") + _ = client.register_task_definition( + family="test_ecs_task", + containerDefinitions=[ + { + "name": "hello_world", + "image": "docker/hello-world:latest", + "cpu": 1024, + "memory": 400, + "essential": True, + "environment": [ + {"name": "AWS_ACCESS_KEY_ID", "value": "SOME_ACCESS_KEY"} + ], + "logConfiguration": {"logDriver": "json-file"}, + } + ], + ) + _ = client.create_service( + cluster="test_ecs_cluster", + serviceName="test_ecs_service", + taskDefinition="test_ecs_task", + desiredCount=2, + ) + response = client.delete_service( + cluster="test_ecs_cluster", service="test_ecs_service", force=True + ) + response["service"]["clusterArn"].should.equal( + "arn:aws:ecs:us-east-1:012345678910:cluster/test_ecs_cluster" + ) + len(response["service"]["events"]).should.equal(0) + len(response["service"]["loadBalancers"]).should.equal(0) + response["service"]["pendingCount"].should.equal(0) + response["service"]["runningCount"].should.equal(0) + response["service"]["serviceArn"].should.equal( + "arn:aws:ecs:us-east-1:012345678910:service/test_ecs_service" + ) + response["service"]["serviceName"].should.equal("test_ecs_service") + response["service"]["status"].should.equal("ACTIVE") + response["service"]["schedulingStrategy"].should.equal("REPLICA") + response["service"]["taskDefinition"].should.equal( + "arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1" + ) + + @mock_ecs def test_delete_service_exceptions(): client = boto3.client("ecs", region_name="us-east-1")