diff --git a/moto/emr/models.py b/moto/emr/models.py index 58f65613c..c73923919 100644 --- a/moto/emr/models.py +++ b/moto/emr/models.py @@ -449,13 +449,64 @@ class FakeCluster(CloudFormationModel): cluster.add_tags(tags) return cluster + @classmethod + def delete_from_cloudformation_json( # type: ignore[misc] + cls, + resource_name: str, + cloudformation_json: Dict[str, Any], + account_id: str, + region_name: str, + ) -> None: + emr_backend: ElasticMapReduceBackend = emr_backends[account_id][region_name] -class FakeSecurityConfiguration(BaseModel): + emr_backend.terminate_job_flows([resource_name]) + + +class FakeSecurityConfiguration(CloudFormationModel): def __init__(self, name: str, security_configuration: str): self.name = name self.security_configuration = security_configuration self.creation_date_time = datetime.now(timezone.utc) + @property + def physical_resource_id(self) -> str: + return self.name + + @staticmethod + def cloudformation_type() -> str: + return "AWS::EMR::SecurityConfiguration" + + @classmethod + def create_from_cloudformation_json( # type: ignore[misc] + cls, + resource_name: str, + cloudformation_json: Any, + account_id: str, + region_name: str, + **kwargs: Any, + ) -> "FakeSecurityConfiguration": + emr_backend: ElasticMapReduceBackend = emr_backends[account_id][region_name] + + properties = cloudformation_json["Properties"] + return emr_backend.create_security_configuration( + name=properties.get("Name") or resource_name, + security_configuration=properties.get("SecurityConfiguration", {}), + ) + + @classmethod + def delete_from_cloudformation_json( # type: ignore[misc] + cls, + resource_name: str, + cloudformation_json: Dict[str, Any], + account_id: str, + region_name: str, + ) -> None: + emr_backend: ElasticMapReduceBackend = emr_backends[account_id][region_name] + + properties = cloudformation_json["Properties"] + name = properties.get("Name") or resource_name + emr_backend.delete_security_configuration(name) + class ElasticMapReduceBackend(BaseBackend): def __init__(self, region_name: str, account_id: str): diff --git a/tests/test_emr/test_emr_cloudformation.py b/tests/test_emr/test_emr_cloudformation.py index 3bebfd22a..84bef4b25 100644 --- a/tests/test_emr/test_emr_cloudformation.py +++ b/tests/test_emr/test_emr_cloudformation.py @@ -1,6 +1,8 @@ import json import boto3 +import pytest +from botocore.exceptions import ClientError from moto import mock_aws from tests import EXAMPLE_AMI_ID @@ -496,6 +498,7 @@ template_with_kerberos_attrs = { "securityConfiguration": { "Type": "AWS::EMR::SecurityConfiguration", "Properties": { + "Name": "mysecconfig", "SecurityConfiguration": { "AuthenticationConfiguration": { "KerberosConfiguration": { @@ -511,7 +514,7 @@ template_with_kerberos_attrs = { }, } } - } + }, }, }, "emrRole": { @@ -618,3 +621,14 @@ def test_create_cluster_with_kerberos_attrs(): "KdcAdminPassword": "adminp2ss", "CrossRealmTrustPrincipalPassword": "p2ss", } + + # Verify everything can be deleted + cf.delete_stack(StackName="teststack") + + cl = emr.describe_cluster(ClusterId=cluster_id)["Cluster"] + assert cl["Status"]["State"] == "TERMINATED" + + with pytest.raises(ClientError) as exc: + emr.describe_security_configuration(Name="mysecconfig") + err = exc.value.response["Error"] + assert err["Code"] == "InvalidRequestException"