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

Add lambda functionality #20

Merged
merged 1 commit into from
Aug 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- support for elbv2 with basic probes and action
- support for asg with basic probes
- fix asg probe to support pagination
- support for lambda with basic probes and action

### Changed

Expand Down
2 changes: 2 additions & 0 deletions chaosaws/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,7 @@ def load_exported_activities() -> List[DiscoveredActivities]:
activities.extend(discover_actions("chaosaws.elbv2.actions"))
activities.extend(discover_probes("chaosaws.elbv2.probes"))
activities.extend(discover_probes("chaosaws.asg.probes"))
activities.extend(discover_actions("chaosaws.awslambda.actions"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it better to name the package just 'lambda', not 'awslambda' to keep the consistency?

Copy link
Contributor Author

@ksolie ksolie Aug 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that but lambda is a reserved word in python. We could change it to lambda_func?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good point, but I think awslambda is clearer than lambda_func, and can see the name collision with simply lambda, which would otherwise be preferred.

activities.extend(discover_probes("chaosaws.awslambda.probes"))

return activities
Empty file added chaosaws/awslambda/__init__.py
Empty file.
41 changes: 41 additions & 0 deletions chaosaws/awslambda/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
from chaoslib.exceptions import FailedActivity
from chaoslib.types import Configuration, Secrets

from chaosaws import aws_client
from chaosaws.types import AWSResponse

__all__ = ["put_function_concurrency", "delete_function_concurrency"]


def put_function_concurrency(function_name: str,
concurrent_executions: int,
configuration: Configuration = None,
secrets: Secrets = None) -> AWSResponse:
"""
Throttles Lambda by setting reserved concurrency amount.
"""
client = aws_client("lambda", configuration, secrets)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be good to check that function_name and concurrent_executions are passed as parameters and not null at least?
I understand that try below is kind of guarding that, but I am afraid the error message could be sometimes misleading if you don't pass parameters

Copy link
Contributor Author

@ksolie ksolie Aug 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't you get a TypeError if they aren't passed in as parameters? I added checking if the function_name string is empty.

if not function_name:
raise FailedActivity(
"you must specify the lambda function name"
)
try:
return client.put_function_concurrency(
FunctionName=function_name,
ReservedConcurrentExecutions=concurrent_executions
)
except Exception as x:
raise FailedActivity(
"failed throttling lambda function '{}': '{}'".format(
function_name, str(x)))


def delete_function_concurrency(function_name: str,
configuration: Configuration = None,
secrets: Secrets = None) -> AWSResponse:
"""
Removes concurrency limit applied to the specified Lambda
"""
client = aws_client("lambda", configuration, secrets)
return client.delete_function_concurrency(FunctionName=function_name)
16 changes: 16 additions & 0 deletions chaosaws/awslambda/probes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
from chaoslib.types import Configuration, Secrets
from chaosaws import aws_client

__all__ = ["get_function_concurrency"]


def get_function_concurrency(function_name: str, configuration:
Configuration = None,
secrets: Secrets = None) -> bool:
"""
Get configuration information of lambda by its function name
"""
client = aws_client("lambda", configuration, secrets)
result = client.get_function(FunctionName=function_name)
return result["Concurrency"]["ReservedConcurrentExecutions"]
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
coverage
moto
moto==1.3.4
pycodestyle
pytest>=2.8
pytest-cov
Expand Down
49 changes: 49 additions & 0 deletions tests/awslambda/test_awslambda_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
from unittest.mock import MagicMock, patch

import pytest
from chaoslib.exceptions import FailedActivity

from chaosaws.awslambda.actions import put_function_concurrency
from chaosaws.awslambda.actions import delete_function_concurrency


@patch('chaosaws.awslambda.actions.aws_client', autospec=True)
def test_aws_lambda_put_function_concurrency(aws_client):
client = MagicMock()
aws_client.return_value = client
lambda_function_name = 'my-lambda-function'
concurrency = 0
put_function_concurrency(lambda_function_name, concurrency)
client.put_function_concurrency.assert_called_with(FunctionName=lambda_function_name,
ReservedConcurrentExecutions=concurrency)

@patch('chaosaws.awslambda.actions.aws_client', autospec=True)
def test_aws_lambda_put_function_concurrency_empty_string(aws_client):
client = MagicMock()
aws_client.return_value = client
lambda_function_name = ''
concurrency = 0
with pytest.raises(FailedActivity):
put_function_concurrency(lambda_function_name, concurrency)


@patch('chaosaws.awslambda.actions.aws_client', autospec=True)
def test_aws_lambda_put_function_concurrency_failedactivity(aws_client):
client = MagicMock()
aws_client.return_value = client
lambda_function_name = 'my-lambda-function'
concurrency = 0

with patch.object(client, 'put_function_concurrency', FailedActivity):
with pytest.raises(Exception):
put_function_concurrency(lambda_function_name, concurrency)


@patch('chaosaws.awslambda.actions.aws_client', autospec=True)
def test_aws_lambda_delete_function_concurrency(aws_client):
client = MagicMock()
aws_client.return_value = client
lambda_function_name = 'my-lambda-function'
delete_function_concurrency(lambda_function_name)
client.delete_function_concurrency.assert_called_with(FunctionName=lambda_function_name)
12 changes: 12 additions & 0 deletions tests/awslambda/test_awslambda_probes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from unittest.mock import MagicMock, patch
from chaosaws.awslambda.probes import get_function_concurrency


@patch('chaosaws.awslambda.probes.aws_client', autospec=True)
def test_aws_lambda_get_function_concurrency(aws_client):
client = MagicMock()
aws_client.return_value = client
lambda_function_name = 'my-lambda-function'
get_function_concurrency(lambda_function_name)
client.get_function.assert_called_with(FunctionName=lambda_function_name)