Elastic Beanstalk: Add the delete_application method support (#6797)

This commit is contained in:
Jean-Frederic Mainville 2023-09-11 04:57:27 -04:00 committed by GitHub
parent 6c04b7b1ce
commit 5e8b457bc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 135 additions and 19 deletions

View File

@ -36,7 +36,7 @@ elasticbeanstalk
- [X] create_environment
- [ ] create_platform_version
- [ ] create_storage_location
- [ ] delete_application
- [x] delete_application
- [ ] delete_application_version
- [ ] delete_configuration_template
- [ ] delete_environment_configuration

View File

@ -1,5 +1,27 @@
from typing import Any
from moto.core.exceptions import RESTError
EXCEPTION_RESPONSE = """<?xml version="1.0"?>
<ErrorResponse xmlns="http://elasticache.amazonaws.com/doc/2015-02-02/">
<Error>
<Type>Sender</Type>
<Code>{{ error_type }}</Code>
<Message>{{ message }}</Message>
</Error>
<{{ request_id_tag }}>30c0dedb-92b1-4e2b-9be4-1188e3ed86ab</{{ request_id_tag }}>
</ErrorResponse>"""
class ElasticBeanstalkException(RESTError):
code = 400
def __init__(self, code: str, message: str, **kwargs: Any):
kwargs.setdefault("template", "ecerror")
self.templates["ecerror"] = EXCEPTION_RESPONSE
super().__init__(code, message)
class InvalidParameterValueError(RESTError):
def __init__(self, message: str):
@ -9,3 +31,14 @@ class InvalidParameterValueError(RESTError):
class ResourceNotFoundException(RESTError):
def __init__(self, message: str):
super().__init__("ResourceNotFoundException", message)
class ApplicationNotFound(ElasticBeanstalkException):
code = 404
def __init__(self, application_name: str):
super().__init__(
"ApplicationNotFound",
message=f"Elastic Beanstalk application {application_name} not found.",
)

View File

@ -2,7 +2,12 @@ import weakref
from typing import Dict, List
from moto.core import BaseBackend, BackendDict, BaseModel
from .exceptions import InvalidParameterValueError, ResourceNotFoundException
from .exceptions import (
InvalidParameterValueError,
ResourceNotFoundException,
ApplicationNotFound,
)
from .utils import make_arn
@ -42,7 +47,11 @@ class FakeEnvironment(BaseModel):
class FakeApplication(BaseModel):
def __init__(self, backend: "EBBackend", application_name: str):
def __init__(
self,
backend: "EBBackend",
application_name: str,
):
self.backend = weakref.proxy(backend) # weakref to break cycles
self.application_name = application_name
self.environments: Dict[str, FakeEnvironment] = dict()
@ -148,5 +157,15 @@ class EBBackend(BaseBackend):
return env
raise KeyError()
def delete_application(
self,
application_name: str,
) -> None:
if application_name:
if application_name in self.applications:
self.applications.pop(application_name)
else:
raise ApplicationNotFound(application_name)
eb_backends = BackendDict(EBBackend, "elasticbeanstalk")

View File

@ -1,7 +1,8 @@
from moto.core.responses import BaseResponse
from moto.core.utils import tags_from_query_string
from .models import eb_backends, EBBackend
from .exceptions import InvalidParameterValueError
from .models import eb_backends, EBBackend
class EBResponse(BaseResponse):
@ -9,35 +10,39 @@ class EBResponse(BaseResponse):
super().__init__(service_name="elasticbeanstalk")
@property
def backend(self) -> EBBackend:
def elasticbeanstalk_backend(self) -> EBBackend:
"""
:rtype: EBBackend
"""
return eb_backends[self.current_account][self.region]
def create_application(self) -> str:
app = self.backend.create_application(
app = self.elasticbeanstalk_backend.create_application(
application_name=self._get_param("ApplicationName")
)
template = self.response_template(EB_CREATE_APPLICATION)
return template.render(region_name=self.backend.region_name, application=app)
return template.render(
region_name=self.elasticbeanstalk_backend.region_name, application=app
)
def describe_applications(self) -> str:
template = self.response_template(EB_DESCRIBE_APPLICATIONS)
return template.render(applications=self.backend.applications.values())
return template.render(
applications=self.elasticbeanstalk_backend.applications.values()
)
def create_environment(self) -> str:
application_name = self._get_param("ApplicationName")
try:
app = self.backend.applications[application_name]
app = self.elasticbeanstalk_backend.applications[application_name]
except KeyError:
raise InvalidParameterValueError(
f"No Application named '{application_name}' found."
)
tags = tags_from_query_string(self.querystring, prefix="Tags.member")
env = self.backend.create_environment(
env = self.elasticbeanstalk_backend.create_environment(
app,
environment_name=self._get_param("EnvironmentName"),
stack_name=self._get_param("SolutionStackName"),
@ -45,10 +50,12 @@ class EBResponse(BaseResponse):
)
template = self.response_template(EB_CREATE_ENVIRONMENT)
return template.render(environment=env, region=self.backend.region_name)
return template.render(
environment=env, region=self.elasticbeanstalk_backend.region_name
)
def describe_environments(self) -> str:
envs = self.backend.describe_environments()
envs = self.elasticbeanstalk_backend.describe_environments()
template = self.response_template(EB_DESCRIBE_ENVIRONMENTS)
return template.render(environments=envs)
@ -62,17 +69,26 @@ class EBResponse(BaseResponse):
self.querystring, prefix="TagsToAdd.member"
)
tags_to_remove = self._get_multi_param("TagsToRemove.member")
self.backend.update_tags_for_resource(resource_arn, tags_to_add, tags_to_remove)
self.elasticbeanstalk_backend.update_tags_for_resource(
resource_arn, tags_to_add, tags_to_remove
)
return EB_UPDATE_TAGS_FOR_RESOURCE
def list_tags_for_resource(self) -> str:
resource_arn = self._get_param("ResourceArn")
tags = self.backend.list_tags_for_resource(resource_arn)
tags = self.elasticbeanstalk_backend.list_tags_for_resource(resource_arn)
template = self.response_template(EB_LIST_TAGS_FOR_RESOURCE)
return template.render(tags=tags, arn=resource_arn)
def delete_application(self) -> str:
application_name = self._get_param("ApplicationName")
self.elasticbeanstalk_backend.delete_application(
application_name=application_name,
)
return DELETE_APPLICATION_TEMPLATE
EB_CREATE_APPLICATION = """
<CreateApplicationResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
@ -105,7 +121,6 @@ EB_CREATE_APPLICATION = """
</CreateApplicationResponse>
"""
EB_DESCRIBE_APPLICATIONS = """
<DescribeApplicationsResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
<DescribeApplicationsResult>
@ -141,6 +156,13 @@ EB_DESCRIBE_APPLICATIONS = """
</DescribeApplicationsResponse>
"""
DELETE_APPLICATION_TEMPLATE = """
<DeleteApplicationResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
<ResponseMetadata>
<RequestId>015a05eb-282e-4b76-bd18-663fdfaf42e4</RequestId>
</ResponseMetadata>
</DeleteApplicationResponse>
"""
EB_CREATE_ENVIRONMENT = """
<CreateEnvironmentResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
@ -167,7 +189,6 @@ EB_CREATE_ENVIRONMENT = """
</CreateEnvironmentResponse>
"""
EB_DESCRIBE_ENVIRONMENTS = """
<DescribeEnvironmentsResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
<DescribeEnvironmentsResult>
@ -207,7 +228,6 @@ EB_DESCRIBE_ENVIRONMENTS = """
</DescribeEnvironmentsResponse>
"""
# Current list as of 2019-09-04
EB_LIST_AVAILABLE_SOLUTION_STACKS = """
<ListAvailableSolutionStacksResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
@ -1359,7 +1379,6 @@ EB_LIST_AVAILABLE_SOLUTION_STACKS = """
</ListAvailableSolutionStacksResponse>
"""
EB_UPDATE_TAGS_FOR_RESOURCE = """
<UpdateTagsForResourceResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
<ResponseMetadata>
@ -1368,7 +1387,6 @@ EB_UPDATE_TAGS_FOR_RESOURCE = """
</UpdateTagsForResourceResponse>
"""
EB_LIST_TAGS_FOR_RESOURCE = """
<ListTagsForResourceResponse xmlns="http://elasticbeanstalk.amazonaws.com/docs/2010-12-01/">
<ListTagsForResourceResult>

View File

View File

@ -34,6 +34,37 @@ def test_describe_applications():
assert "myapp" in apps["Applications"][0]["ApplicationArn"]
@mock_elasticbeanstalk
def test_delete_application():
conn = boto3.client("elasticbeanstalk", region_name="us-east-1")
application_name = "myapp"
conn.create_application(ApplicationName=application_name)
resp = conn.delete_application(ApplicationName=application_name)
assert resp["ResponseMetadata"]["HTTPStatusCode"] == 200
@mock_elasticbeanstalk
def test_delete_unknown_application():
conn = boto3.client("elasticbeanstalk", region_name="us-east-1")
application_name = "myapp"
unknown_application_name = "myapp1"
conn.create_application(ApplicationName=application_name)
with pytest.raises(ClientError) as exc:
conn.delete_application(ApplicationName=unknown_application_name)
err = exc.value.response["Error"]
assert err["Code"] == "ApplicationNotFound"
assert (
err["Message"]
== f"Elastic Beanstalk application {unknown_application_name} not found."
)
@mock_elasticbeanstalk
def test_create_environment():
# Create Elastic Beanstalk Environment

View File

@ -0,0 +1,15 @@
"""Test different server responses."""
import moto.server as server
def test_elasticbeanstalk_describe():
backend = server.create_backend_app("elasticbeanstalk")
test_client = backend.test_client()
data = "Action=DescribeApplications"
headers = {"Host": "elasticbeanstalk.us-east-1.amazonaws.com"}
resp = test_client.post("/", data=data, headers=headers)
assert resp.status_code == 200
assert "<Applications></Applications>" in str(resp.data)