ECS - Enable option to use new ARN format (#4450)
This commit is contained in:
parent
125936d269
commit
7f0ef4a0cc
@ -7,6 +7,7 @@ from random import random, randint
|
||||
import pytz
|
||||
from boto3 import Session
|
||||
|
||||
from moto import settings
|
||||
from moto.core import BaseBackend, BaseModel, CloudFormationModel, ACCOUNT_ID
|
||||
from moto.core.exceptions import JsonRESTError
|
||||
from moto.core.utils import unix_time, pascal_to_camelcase, remap_nested_keys
|
||||
@ -272,10 +273,9 @@ class Task(BaseObject):
|
||||
started_by="",
|
||||
tags=[],
|
||||
):
|
||||
self.id = str(uuid.uuid4())
|
||||
self.cluster_name = cluster.name
|
||||
self.cluster_arn = cluster.arn
|
||||
self.task_arn = "arn:aws:ecs:{0}:{1}:task/{2}".format(
|
||||
cluster.region_name, ACCOUNT_ID, str(uuid.uuid4())
|
||||
)
|
||||
self.container_instance_arn = container_instance_arn
|
||||
self.last_status = "RUNNING"
|
||||
self.desired_status = "RUNNING"
|
||||
@ -286,10 +286,20 @@ class Task(BaseObject):
|
||||
self.tags = tags
|
||||
self.stopped_reason = ""
|
||||
self.resource_requirements = resource_requirements
|
||||
self.region_name = cluster.region_name
|
||||
|
||||
@property
|
||||
def task_arn(self):
|
||||
if settings.ecs_new_arn_format():
|
||||
return f"arn:aws:ecs:{self.region_name}:{ACCOUNT_ID}:task/{self.cluster_name}/{self.id}"
|
||||
return "arn:aws:ecs:{0}:{1}:task/{2}".format(
|
||||
self.region_name, ACCOUNT_ID, self.id
|
||||
)
|
||||
|
||||
@property
|
||||
def response_object(self):
|
||||
response_object = self.gen_response_object()
|
||||
response_object["taskArn"] = self.task_arn
|
||||
return response_object
|
||||
|
||||
|
||||
@ -307,10 +317,8 @@ class Service(BaseObject, CloudFormationModel):
|
||||
launch_type=None,
|
||||
service_registries=None,
|
||||
):
|
||||
self.cluster_name = cluster.name
|
||||
self.cluster_arn = cluster.arn
|
||||
self.arn = "arn:aws:ecs:{0}:{1}:service/{2}".format(
|
||||
cluster.region_name, ACCOUNT_ID, service_name
|
||||
)
|
||||
self.name = service_name
|
||||
self.status = "ACTIVE"
|
||||
self.running_count = 0
|
||||
@ -346,6 +354,15 @@ class Service(BaseObject, CloudFormationModel):
|
||||
)
|
||||
self.tags = tags if tags is not None else []
|
||||
self.pending_count = 0
|
||||
self.region_name = cluster.region_name
|
||||
|
||||
@property
|
||||
def arn(self):
|
||||
if settings.ecs_new_arn_format():
|
||||
return f"arn:aws:ecs:{self.region_name}:{ACCOUNT_ID}:service/{self.cluster_name}/{self.name}"
|
||||
return "arn:aws:ecs:{0}:{1}:service/{2}".format(
|
||||
self.region_name, ACCOUNT_ID, self.name
|
||||
)
|
||||
|
||||
@property
|
||||
def physical_resource_id(self):
|
||||
@ -354,7 +371,7 @@ class Service(BaseObject, CloudFormationModel):
|
||||
@property
|
||||
def response_object(self):
|
||||
response_object = self.gen_response_object()
|
||||
del response_object["name"], response_object["arn"], response_object["tags"]
|
||||
del response_object["name"], response_object["tags"]
|
||||
response_object["serviceName"] = self.name
|
||||
response_object["serviceArn"] = self.arn
|
||||
response_object["schedulingStrategy"] = self.scheduling_strategy
|
||||
@ -450,7 +467,7 @@ class Service(BaseObject, CloudFormationModel):
|
||||
|
||||
|
||||
class ContainerInstance(BaseObject):
|
||||
def __init__(self, ec2_instance_id, region_name):
|
||||
def __init__(self, ec2_instance_id, region_name, cluster_name):
|
||||
self.ec2_instance_id = ec2_instance_id
|
||||
self.agent_connected = True
|
||||
self.status = "ACTIVE"
|
||||
@ -486,9 +503,6 @@ class ContainerInstance(BaseObject):
|
||||
"type": "STRINGSET",
|
||||
},
|
||||
]
|
||||
self.container_instance_arn = "arn:aws:ecs:{0}:{1}:container-instance/{2}".format(
|
||||
region_name, ACCOUNT_ID, str(uuid.uuid4())
|
||||
)
|
||||
self.pending_tasks_count = 0
|
||||
self.remaining_resources = [
|
||||
{
|
||||
@ -539,10 +553,22 @@ class ContainerInstance(BaseObject):
|
||||
else "linux", # options are windows and linux, linux is default
|
||||
}
|
||||
self.registered_at = datetime.now(pytz.utc)
|
||||
self.region_name = region_name
|
||||
self.id = str(uuid.uuid4())
|
||||
self.cluster_name = cluster_name
|
||||
|
||||
@property
|
||||
def container_instance_arn(self):
|
||||
if settings.ecs_new_arn_format():
|
||||
return f"arn:aws:ecs:{self.region_name}:{ACCOUNT_ID}:container-instance/{self.cluster_name}/{self.id}"
|
||||
return (
|
||||
f"arn:aws:ecs:{self.region_name}:{ACCOUNT_ID}:container-instance/{self.id}"
|
||||
)
|
||||
|
||||
@property
|
||||
def response_object(self):
|
||||
response_object = self.gen_response_object()
|
||||
response_object["containerInstanceArn"] = self.container_instance_arn
|
||||
response_object["attributes"] = [
|
||||
self._format_attribute(name, value)
|
||||
for name, value in response_object["attributes"].items()
|
||||
@ -1198,7 +1224,9 @@ class EC2ContainerServiceBackend(BaseBackend):
|
||||
cluster_name = cluster_str.split("/")[-1]
|
||||
if cluster_name not in self.clusters:
|
||||
raise Exception("{0} is not a cluster".format(cluster_name))
|
||||
container_instance = ContainerInstance(ec2_instance_id, self.region_name)
|
||||
container_instance = ContainerInstance(
|
||||
ec2_instance_id, self.region_name, cluster_name
|
||||
)
|
||||
if not self.container_instances.get(cluster_name):
|
||||
self.container_instances[cluster_name] = {}
|
||||
container_instance_id = container_instance.container_instance_arn.split("/")[-1]
|
||||
|
@ -32,3 +32,7 @@ def get_s3_default_key_buffer_size():
|
||||
"MOTO_S3_DEFAULT_KEY_BUFFER_SIZE", S3_UPLOAD_PART_MIN_SIZE - 1024
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def ecs_new_arn_format():
|
||||
return os.environ.get("MOTO_ECS_NEW_ARN", "false").lower() == "true"
|
||||
|
@ -2,15 +2,16 @@ from datetime import datetime
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
import boto3
|
||||
import mock
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
import json
|
||||
import os
|
||||
|
||||
from moto.core import ACCOUNT_ID
|
||||
from moto.ec2 import utils as ec2_utils
|
||||
from uuid import UUID
|
||||
|
||||
from moto import mock_ecs
|
||||
from moto import mock_ec2
|
||||
from moto import mock_ecs, mock_ec2, settings
|
||||
from moto.ecs.exceptions import (
|
||||
ClusterNotFoundException,
|
||||
ServiceNotFoundException,
|
||||
@ -20,6 +21,7 @@ from moto.ecs.exceptions import (
|
||||
)
|
||||
import pytest
|
||||
from tests import EXAMPLE_AMI_ID
|
||||
from unittest import SkipTest
|
||||
|
||||
|
||||
@mock_ecs
|
||||
@ -724,6 +726,36 @@ def test_describe_services():
|
||||
response["services"][1]["launchType"].should.equal("EC2")
|
||||
|
||||
|
||||
@mock_ecs
|
||||
@mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": "TrUe"})
|
||||
def test_describe_services_new_arn():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Cant set environment variables in server mode")
|
||||
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",}
|
||||
],
|
||||
)
|
||||
_ = client.create_service(
|
||||
cluster="test_ecs_cluster",
|
||||
serviceName="test_ecs_service1",
|
||||
taskDefinition="test_ecs_task",
|
||||
desiredCount=2,
|
||||
tags=[{"key": "Name", "value": "test_ecs_service1"}],
|
||||
)
|
||||
response = client.describe_services(
|
||||
cluster="test_ecs_cluster", services=["test_ecs_service1"]
|
||||
)
|
||||
response["services"][0]["serviceArn"].should.equal(
|
||||
"arn:aws:ecs:us-east-1:{}:service/test_ecs_cluster/test_ecs_service1".format(
|
||||
ACCOUNT_ID
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@mock_ecs
|
||||
def test_describe_services_scheduling_strategy():
|
||||
client = boto3.client("ecs", region_name="us-east-1")
|
||||
@ -1125,6 +1157,37 @@ def test_register_container_instance():
|
||||
)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_ecs
|
||||
@mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": "TrUe"})
|
||||
def test_register_container_instance_new_arn_format():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Cant set environment variables in server mode")
|
||||
ecs_client = boto3.client("ecs", region_name="us-east-1")
|
||||
ec2 = boto3.resource("ec2", region_name="us-east-1")
|
||||
|
||||
test_cluster_name = "test_ecs_cluster"
|
||||
|
||||
ecs_client.create_cluster(clusterName=test_cluster_name)
|
||||
|
||||
test_instance = ec2.create_instances(
|
||||
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1
|
||||
)[0]
|
||||
|
||||
instance_id_document = json.dumps(
|
||||
ec2_utils.generate_instance_identity_document(test_instance)
|
||||
)
|
||||
|
||||
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-]+$"
|
||||
)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_ecs
|
||||
def test_deregister_container_instance():
|
||||
@ -1545,8 +1608,8 @@ def test_run_task_default_cluster():
|
||||
startedBy="moto",
|
||||
)
|
||||
len(response["tasks"]).should.equal(2)
|
||||
response["tasks"][0]["taskArn"].should.contain(
|
||||
"arn:aws:ecs:us-east-1:{}:task/".format(ACCOUNT_ID)
|
||||
response["tasks"][0]["taskArn"].should.match(
|
||||
"arn:aws:ecs:us-east-1:{}:task/[a-z0-9-]+$".format(ACCOUNT_ID)
|
||||
)
|
||||
response["tasks"][0]["clusterArn"].should.equal(
|
||||
"arn:aws:ecs:us-east-1:{}:cluster/default".format(ACCOUNT_ID)
|
||||
@ -1564,6 +1627,54 @@ def test_run_task_default_cluster():
|
||||
response["tasks"][0]["stoppedReason"].should.equal("")
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_ecs
|
||||
@mock.patch.dict(os.environ, {"MOTO_ECS_NEW_ARN": "TrUe"})
|
||||
def test_run_task_default_cluster_new_arn_format():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Cant set environment variables in server mode")
|
||||
client = boto3.client("ecs", region_name="us-east-1")
|
||||
ec2 = boto3.resource("ec2", region_name="us-east-1")
|
||||
|
||||
test_cluster_name = "default"
|
||||
|
||||
client.create_cluster(clusterName=test_cluster_name)
|
||||
|
||||
test_instance = ec2.create_instances(
|
||||
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1
|
||||
)[0]
|
||||
|
||||
instance_id_document = json.dumps(
|
||||
ec2_utils.generate_instance_identity_document(test_instance)
|
||||
)
|
||||
|
||||
client.register_container_instance(
|
||||
cluster=test_cluster_name, instanceIdentityDocument=instance_id_document
|
||||
)
|
||||
|
||||
client.register_task_definition(
|
||||
family="test_ecs_task",
|
||||
containerDefinitions=[
|
||||
{
|
||||
"name": "hello_world",
|
||||
"image": "docker/hello-world:latest",
|
||||
"cpu": 1024,
|
||||
"memory": 400,
|
||||
}
|
||||
],
|
||||
)
|
||||
response = client.run_task(
|
||||
launchType="FARGATE",
|
||||
overrides={},
|
||||
taskDefinition="test_ecs_task",
|
||||
count=1,
|
||||
startedBy="moto",
|
||||
)
|
||||
response["tasks"][0]["taskArn"].should.match(
|
||||
f"arn:aws:ecs:us-east-1:{ACCOUNT_ID}:task/{test_cluster_name}/[a-z0-9-]+$"
|
||||
)
|
||||
|
||||
|
||||
@mock_ecs
|
||||
def test_run_task_exceptions():
|
||||
client = boto3.client("ecs", region_name="us-east-1")
|
||||
@ -1849,7 +1960,7 @@ def test_describe_task_definition_by_family():
|
||||
task["containerDefinitions"][0].should.equal(
|
||||
dict(
|
||||
container_definition,
|
||||
**{"mountPoints": [], "portMappings": [], "volumesFrom": []}
|
||||
**{"mountPoints": [], "portMappings": [], "volumesFrom": []},
|
||||
)
|
||||
)
|
||||
task["taskDefinitionArn"].should.equal(
|
||||
|
Loading…
Reference in New Issue
Block a user