Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory and CPU missing in ECS task definition #3222

Closed
ipmb opened this issue Aug 9, 2020 · 2 comments
Closed

Memory and CPU missing in ECS task definition #3222

ipmb opened this issue Aug 9, 2020 · 2 comments

Comments

@ipmb
Copy link
Contributor

ipmb commented Aug 9, 2020

Calling the ecs client's register_task_definition method with cpu and memory does not save them as part of the task definition.

>>> import os
>>> os.environ['AWS_ACCESS_KEY_ID'] = 'testing'
>>> os.environ['AWS_SECRET_ACCESS_KEY'] = 'testing'
>>> os.environ['AWS_SESSION_TOKEN'] = 'testing'
>>> os.environ['AWS_SECURITY_TOKEN'] = 'testing'
>>> os.environ['AWS_DEFAULT_REGION'] = 'us-east-1'
>>> import moto
>>> mock = moto.mock_ecs()
>>> mock.start()
>>> import boto3
>>> ecs = boto3.client("ecs")
>>> kwargs = {'containerDefinitions': [{'environment': [{'name': 'APPNAME', 'value': 'my-app'}, {'name': 'CNB_PROCESS_TYPE', 'value': 'release'}], 'image': '123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app-stage:b35ce1cc53cd399d4c1143b4506c9820c2e3e739', 'linuxParameters': {'initProcessEnabled': True}, 'logConfiguration': {'logDriver': 'awslogs', 'options': {'awslogs-group': '/aws/ecs/default/my-app', 'awslogs-region': 'us-east-1', 'awslogs-stream-prefix': 'release'}}, 'name': 'release', 'secrets': []}], 'cpu': '256', 'executionRoleArn': 'arn:aws:iam::123456789012:role/paaws/ecs-tasks-execution-my-app-service-role', 'memory': '512'}
>>> resp = ecs.register_task_definition(family='my-app-release', **kwargs)
>>> resp["taskDefinition"]
{'taskDefinitionArn': 'arn:aws:ecs:us-east-1:012345678910:task-definition/my-app-release:1', 'containerDefinitions': [{'name': 'release', 'image': '123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app-stage:b35ce1cc53cd399d4c1143b4506c9820c2e3e739', 'environment': [{'name': 'APPNAME', 'value': 'my-app'}, {'name': 'CNB_PROCESS_TYPE', 'value': 'release'}], 'linuxParameters': {'initProcessEnabled': True}, 'secrets': [], 'logConfiguration': {'logDriver': 'awslogs', 'options': {'awslogs-group': '/aws/ecs/default/my-app', 'awslogs-region': 'us-east-1', 'awslogs-stream-prefix': 'release'}}}], 'family': 'my-app-release', 'networkMode': 'bridge', 'revision': 1, 'volumes': [], 'placementConstraints': []}
>>> kwargs['memory']
'512'
>>> resp['memory']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'memory'

My expectation is that they are stored with the task definition. Not having them stored in the task definition prevents ever running a task using the definition. The following traceback is triggered:

orchestrator/common.py:468: in run_task
    ret_val = ecs.run_task(
.venv/lib/python3.8/site-packages/botocore/client.py:316: in _api_call
    return self._make_api_call(operation_name, kwargs)
.venv/lib/python3.8/site-packages/botocore/client.py:621: in _make_api_call
    http, parsed_response = self._make_request(
.venv/lib/python3.8/site-packages/botocore/client.py:641: in _make_request
    return self._endpoint.make_request(operation_model, request_dict)
.venv/lib/python3.8/site-packages/botocore/endpoint.py:102: in make_request
    return self._send_request(request_dict, operation_model)
.venv/lib/python3.8/site-packages/botocore/endpoint.py:136: in _send_request
    while self._needs_retry(attempts, operation_model, request_dict,
.venv/lib/python3.8/site-packages/botocore/endpoint.py:253: in _needs_retry
    responses = self._event_emitter.emit(
.venv/lib/python3.8/site-packages/botocore/hooks.py:356: in emit
    return self._emitter.emit(aliased_event_name, **kwargs)
.venv/lib/python3.8/site-packages/botocore/hooks.py:228: in emit
    return self._emit(event_name, kwargs)
.venv/lib/python3.8/site-packages/botocore/hooks.py:211: in _emit
    response = handler(**kwargs)
.venv/lib/python3.8/site-packages/botocore/retryhandler.py:183: in __call__
    if self._checker(attempts, response, caught_exception):
.venv/lib/python3.8/site-packages/botocore/retryhandler.py:250: in __call__
    should_retry = self._should_retry(attempt_number, response,
.venv/lib/python3.8/site-packages/botocore/retryhandler.py:269: in _should_retry
    return self._checker(attempt_number, response, caught_exception)
.venv/lib/python3.8/site-packages/botocore/retryhandler.py:316: in __call__
    checker_response = checker(attempt_number, response,
.venv/lib/python3.8/site-packages/botocore/retryhandler.py:222: in __call__
    return self._check_caught_exception(
.venv/lib/python3.8/site-packages/botocore/retryhandler.py:359: in _check_caught_exception
    raise caught_exception
.venv/lib/python3.8/site-packages/botocore/endpoint.py:197: in _do_get_response
    responses = self._event_emitter.emit(event_name, request=request)
.venv/lib/python3.8/site-packages/botocore/hooks.py:356: in emit
    return self._emitter.emit(aliased_event_name, **kwargs)
.venv/lib/python3.8/site-packages/botocore/hooks.py:228: in emit
    return self._emit(event_name, kwargs)
.venv/lib/python3.8/site-packages/botocore/hooks.py:211: in _emit
    response = handler(**kwargs)
.venv/lib/python3.8/site-packages/moto/core/models.py:322: in __call__
    status, headers, body = response_callback(
.venv/lib/python3.8/site-packages/moto/core/responses.py:202: in dispatch
    return cls()._dispatch(*args, **kwargs)
.venv/lib/python3.8/site-packages/moto/core/responses.py:312: in _dispatch
    return self.call_action()
.venv/lib/python3.8/site-packages/moto/core/responses.py:397: in call_action
    response = method()
.venv/lib/python3.8/site-packages/moto/ecs/responses.py:105: in run_task
    tasks = self.ecs_backend.run_task(
.venv/lib/python3.8/site-packages/moto/ecs/models.py:758: in run_task
    resource_requirements = self._calculate_task_resource_requirements(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

task_definition = <moto.ecs.models.TaskDefinition object at 0x1091ad5e0>

    @staticmethod
    def _calculate_task_resource_requirements(task_definition):
        resource_requirements = {"CPU": 0, "MEMORY": 0, "PORTS": [], "PORTS_UDP": []}
        for container_definition in task_definition.container_definitions:
            # cloudformation uses capitalized properties, while boto uses all lower case

            # CPU is optional
            resource_requirements["CPU"] += container_definition.get(
                "cpu", container_definition.get("Cpu", 0)
            )

            # either memory or memory reservation must be provided
            if (
                "Memory" in container_definition
                or "MemoryReservation" in container_definition
            ):
                resource_requirements["MEMORY"] += container_definition.get(
                    "Memory", container_definition.get("MemoryReservation")
                )
            else:
>               resource_requirements["MEMORY"] += container_definition.get(
                    "memory", container_definition.get("memoryReservation")
                )
E               TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'

.venv/lib/python3.8/site-packages/moto/ecs/models.py:814: TypeError

Versions:

$ pip freeze | grep oto
boto==2.49.0
boto3==1.14.29
botocore==1.17.29
moto @ https://github.com/spulec/moto/archive/master.zip
$ python --version
Python 3.8.2

Issue is seen, both on moto 1.3.14 and the current master branch at 9894e1785a610f1dd8c9bfce1fa416692b3e0c2f.

@bblommers
Copy link
Collaborator

Thanks for raising this @ipmb - marking this as an enhancement

@bblommers
Copy link
Collaborator

The immediate bug behind this issue was fixed in #3584, so I'll close this.
I'll leave the attached PR open, as that does have potential for improved validation if the user supplied wrong values for the memory/CPU.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants