Skip to content

Commit

Permalink
ECS - LongARN is enabled by default (#4762)
Browse files Browse the repository at this point in the history
  • Loading branch information
bblommers authored Jan 18, 2022
1 parent 6610862 commit 291aa83
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 46 deletions.
2 changes: 2 additions & 0 deletions docs/docs/services/ecs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
ecs
===

.. autoclass:: moto.ecs.models.EC2ContainerServiceBackend

|start-h3| Example usage |end-h3|

.. sourcecode:: python
Expand Down
24 changes: 18 additions & 6 deletions moto/ecs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,14 @@ def response_object(self):


class EC2ContainerServiceBackend(BaseBackend):
"""
ECS resources use the new ARN format by default.
Use the following environment variable to revert back to the old/short ARN format:
`MOTO_ECS_NEW_ARN=false`
AWS reference: https://aws.amazon.com/blogs/compute/migrating-your-amazon-ecs-deployment-to-the-new-arn-and-resource-id-format-2/
"""

def __init__(self, region_name):
super().__init__()
self.account_settings = dict()
Expand Down Expand Up @@ -1558,9 +1566,15 @@ def list_task_definition_families(
@staticmethod
def _parse_resource_arn(resource_arn):
match = re.match(
"^arn:aws:ecs:(?P<region>[^:]+):(?P<account_id>[^:]+):(?P<service>[^:]+)/(?P<id>.*)$",
"^arn:aws:ecs:(?P<region>[^:]+):(?P<account_id>[^:]+):(?P<service>[^:]+)/(?P<cluster_id>[^:]+)/(?P<id>.*)$",
resource_arn,
)
if not match:
# maybe a short-format ARN
match = re.match(
"^arn:aws:ecs:(?P<region>[^:]+):(?P<account_id>[^:]+):(?P<service>[^:]+)/(?P<id>.*)$",
resource_arn,
)
if not match:
raise JsonRESTError(
"InvalidParameterException", "The ARN provided is invalid."
Expand Down Expand Up @@ -1784,12 +1798,10 @@ def delete_account_setting(self, name):
self.account_settings.pop(name, None)

def enable_long_arn_for_name(self, name):
if settings.ecs_new_arn_format():
return True
account = self.account_settings.get(name, None)
if account and account.value == "enabled":
return True
return False
if account and account.value == "disabled":
return False
return settings.ecs_new_arn_format()


ecs_backends = BackendDict(EC2ContainerServiceBackend, "ecs")
3 changes: 2 additions & 1 deletion moto/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def get_s3_default_key_buffer_size():


def ecs_new_arn_format():
return os.environ.get("MOTO_ECS_NEW_ARN", "false").lower() == "true"
# True by default - only the value 'false' will return false
return os.environ.get("MOTO_ECS_NEW_ARN", "true").lower() != "false"


def allow_unknown_region():
Expand Down
27 changes: 27 additions & 0 deletions tests/test_core/test_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
import mock
import pytest
import sure # noqa # pylint: disable=unused-import

from moto import settings


"""
Sanity checks for interpretation of the MOTO_ECS_NEW_ARN-variable
"""


def test_default_is_true():
settings.ecs_new_arn_format().should.equal(True)


@pytest.mark.parametrize("value", ["TrUe", "true", "invalid", "0", "1"])
def test_anything_but_false_is_true(value):
with mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": value}):
settings.ecs_new_arn_format().should.equal(True)


@pytest.mark.parametrize("value", ["False", "false", "faLse"])
def test_only_false_is_false(value):
with mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": value}):
settings.ecs_new_arn_format().should.equal(False)
36 changes: 18 additions & 18 deletions tests/test_ecs/test_ecs_account_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def test_delete_account_setting():
@mock_ecs
def test_put_account_setting_changes_service_arn():
client = boto3.client("ecs", region_name="eu-west-1")
client.put_account_setting(name="serviceLongArnFormat", value="enabled")
client.put_account_setting(name="serviceLongArnFormat", value="disabled")

_ = client.create_cluster(clusterName="dummy-cluster")
_ = client.register_task_definition(
Expand All @@ -126,21 +126,21 @@ def test_put_account_setting_changes_service_arn():
tags=[{"key": "ResourceOwner", "value": "Dummy"}],
)

# Initial response is long
# Initial response is short (setting serviceLongArnFormat=disabled)
response = client.list_services(cluster="dummy-cluster", launchType="FARGATE")
service_arn = response["serviceArns"][0]
service_arn.should.equal(
"arn:aws:ecs:eu-west-1:{}:service/dummy-cluster/test-ecs-service".format(
ACCOUNT_ID
)
"arn:aws:ecs:eu-west-1:{}:service/test-ecs-service".format(ACCOUNT_ID)
)

# Second invocation returns short ARN's, after deleting the longArn-preference
# Second invocation returns long ARN's by default, after deleting the preference
client.delete_account_setting(name="serviceLongArnFormat")
response = client.list_services(cluster="dummy-cluster", launchType="FARGATE")
service_arn = response["serviceArns"][0]
service_arn.should.equal(
"arn:aws:ecs:eu-west-1:{}:service/test-ecs-service".format(ACCOUNT_ID)
"arn:aws:ecs:eu-west-1:{}:service/dummy-cluster/test-ecs-service".format(
ACCOUNT_ID
)
)


Expand All @@ -162,25 +162,25 @@ def test_put_account_setting_changes_containerinstance_arn():
ec2_utils.generate_instance_identity_document(test_instance)
)

# Initial ARN should be short
# Initial ARN should be long
response = ecs_client.register_container_instance(
cluster=test_cluster_name, instanceIdentityDocument=instance_id_document
)
full_arn = response["containerInstance"]["containerInstanceArn"]
full_arn.should.match(
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:container-instance/[a-z0-9-]+$"
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:container-instance/{test_cluster_name}/[a-z0-9-]+$"
)

# Now enable long-format
# Now disable long-format
ecs_client.put_account_setting(
name="containerInstanceLongArnFormat", value="enabled"
name="containerInstanceLongArnFormat", value="disabled"
)
response = ecs_client.register_container_instance(
cluster=test_cluster_name, instanceIdentityDocument=instance_id_document
)
full_arn = response["containerInstance"]["containerInstanceArn"]
full_arn.should.match(
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:container-instance/{test_cluster_name}/[a-z0-9-]+$"
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:container-instance/[a-z0-9-]+$"
)


Expand Down Expand Up @@ -217,8 +217,8 @@ def test_run_task_default_cluster_new_arn_format():
}
],
)
# Initial ARN is short-format
client.put_account_setting(name="taskLongArnFormat", value="disabled")
# Initial ARN is long-format
client.put_account_setting(name="taskLongArnFormat", value="enabled")
response = client.run_task(
launchType="FARGATE",
overrides={},
Expand All @@ -227,11 +227,11 @@ def test_run_task_default_cluster_new_arn_format():
startedBy="moto",
)
response["tasks"][0]["taskArn"].should.match(
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:task/[a-z0-9-]+$"
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:task/{test_cluster_name}/[a-z0-9-]+$"
)

# Enable long-format for the next task
client.put_account_setting(name="taskLongArnFormat", value="enabled")
# Enable short-format for the next task
client.put_account_setting(name="taskLongArnFormat", value="disabled")
response = client.run_task(
launchType="FARGATE",
overrides={},
Expand All @@ -240,5 +240,5 @@ def test_run_task_default_cluster_new_arn_format():
startedBy="moto",
)
response["tasks"][0]["taskArn"].should.match(
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:task/{test_cluster_name}/[a-z0-9-]+$"
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:task/[a-z0-9-]+$"
)
Loading

0 comments on commit 291aa83

Please sign in to comment.