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

Release: 0.6.2 Release #752

Merged
merged 25 commits into from
Nov 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a3eb631
fix: Support attaching to host network
jfuss Oct 18, 2018
2c5388b
chore: Enable Travis to run integ tests
jfuss Oct 22, 2018
5991014
fix: Iterate over query param list
jfuss Oct 23, 2018
8d3bab2
docs: Update Docker command to docker (#725)
codesterribly Oct 24, 2018
d83ea61
docs: add instructions for using local version of SAM Transformer (#688)
brettstack Oct 24, 2018
0bafa5c
Merge branch 'develop' into update-travis
sriram-mv Oct 24, 2018
d423288
Update README.rst
latheesan-k Oct 25, 2018
2c25059
chore: Version bump aws-sam-translator to 1.8.0 (#732)
keetonian Oct 26, 2018
a1f6d82
Merge branch 'develop' into update-travis
sanathkr Oct 26, 2018
ec5c62b
Merge pull request #722 from jfuss/update-travis
sriram-mv Oct 26, 2018
94a0e36
Fix typo
xiangshen-dk Oct 28, 2018
bbe822d
fix: upgrade requests to 2.20.0 (#740)
sriram-mv Oct 30, 2018
1d276ea
Fix: Travis times out when running Integ tests (#739)
jfuss Nov 1, 2018
fe8fd00
Merge branch 'develop' into patch-1
jfuss Nov 1, 2018
f7ef963
Merge branch 'develop' into support-host-network
sriram-mv Nov 6, 2018
df7e313
chore(version_bump): bump to 0.6.2
sriram-mv Nov 6, 2018
371321f
Merge pull request #715 from jfuss/support-host-network
sriram-mv Nov 6, 2018
ca70140
Merge branch 'develop' into patch-1
sriram-mv Nov 6, 2018
f513b43
Merge branch 'develop' into develop
sriram-mv Nov 7, 2018
80ed232
Merge branch 'develop' into version_bump
jfuss Nov 7, 2018
a5fea1c
Merge pull request #734 from xiangshen-dk/patch-1
sriram-mv Nov 7, 2018
76d3b83
Merge branch 'develop' into develop
sriram-mv Nov 7, 2018
b8e616a
Merge pull request #730 from latheesan-k/develop
sriram-mv Nov 7, 2018
092ac01
Merge branch 'develop' into version_bump
sriram-mv Nov 7, 2018
480979f
Merge pull request #750 from TheSriram/version_bump
sriram-mv Nov 7, 2018
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
12 changes: 9 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Enable container based builds
sudo: false
sudo: required
language: python

services:
- docker

python:
- "2.7"
- "3.6"

env:
global:
- AWS_DEFAULT_REGION=us-east-1

# Enable 3.7 without globally enabling sudo and dist: xenial for other build jobs
matrix:
include:
Expand All @@ -17,8 +24,7 @@ install:
# Install the code requirements
- make init

# Install Docs requirements

script:
# Runs unit tests
- make pr
- SAM_CLI_DEV=1 travis_wait pytest -vv tests/integration
26 changes: 26 additions & 0 deletions DEVELOPMENT_GUIDE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,32 @@ if any.
#. Install dev CLI: ``make init``
#. Make sure installation succeeded: ``which samdev``

4. (Optional) Install development version of SAM Transformer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you want to run the latest version of [SAM Transformer](https://github.com/awslabs/serverless-application-model/), you can clone it locally and install it in your pyenv. This is useful if you want to validate your templates against any new, unreleased SAM features ahead of time.

This step is optional and will use the specified version of aws-sam-transformer from PyPi by default.

```bash
# cd into the directory where you usually place projects and clone the latest SAM Transformer
cd ~/projects
git clone https://github.com/awslabs/serverless-application-model/

# cd into the new directory and checkout the relevant branch
cd serverless-application-model
git checkout develop

# Install the SAM Transformer in editable mode so that all changes you make to
# the SAM Transformer locally are immediately picked up for SAM CLI.
pip install -e .

# Move back to your SAM CLI directory and re-run init
# If necessary: open requirements/base.txt and replace the version number of aws-sam-translator with the
# version number specified in your local version of serverless-application-model/samtranslator/__init__.py
cd ../aws-sam-cli
make init
```

Running Tests
-------------
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Learn how to get started using the SAM CLI with these guides:
- `Running and debugging serverless applications locally <docs/usage.rst>`__: Describes how to use SAM CLI for invoking Lambda functions locally, running automated tests, fetching logs, and debugging applications
- `Packaging and deploying your application <docs/deploying_serverless_applications.rst>`__: Deploy your local application using an S3 bucket, and AWS CloudFormation.
- `Advanced <docs/advanced_usage.rst>`__: Learn how to work with compiled languages (such as Java and .NET), configure IAM credentials, provide environment variables, and more.
- `Examples <#examples>`__
- `Examples <https://github.com/awslabs/serverless-application-model/tree/master/examples/apps>`__


Project Status
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ environment variable to contact the docker daemon.
pip install --upgrade setuptools
pip install --upgrade aws-sam-cli
*** if you want to use the lambda-local option(without running it as root) you will need to add your user to the docker group ***
usermod -a -G Docker yourUserName
usermod -a -G docker yourUserName

**Note for macOS and Windows users**: SAM CLI requires that the project directory
(or any parent directory) is listed in `Docker file sharing options <https://docs.docker.com/docker-for-mac/osxfs/>`__.
Expand Down
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Flask~=1.0.2
boto3~=1.5
PyYAML~=3.12
cookiecutter~=1.6.0
aws-sam-translator==1.7.0
aws-sam-translator==1.8.0
docker>=3.3.0
dateparser~=0.7
python-dateutil~=2.6
Expand Down
2 changes: 1 addition & 1 deletion requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pylint==1.7.2
pytest==3.0.7
py==1.4.33
mock==2.0.0
requests==2.19.0
requests==2.20.0
parameterized==0.6.1
pathlib2==2.3.2; python_version<"3.4"
futures==3.2.0; python_version<"3.2.3"
Expand Down
2 changes: 1 addition & 1 deletion samcli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
SAM CLI version
"""

__version__ = '0.6.1'
__version__ = '0.6.2'
2 changes: 1 addition & 1 deletion samcli/local/apigw/local_apigw_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def _query_string_params(flask_request):

# Flask returns an ImmutableMultiDict so convert to a dictionary that becomes
# a dict(str: list) then iterate over
for query_string_key, query_string_list in dict(flask_request.args).items():
for query_string_key, query_string_list in flask_request.args.lists():
query_string_value_length = len(query_string_list)

# if the list is empty, default to empty string
Expand Down
5 changes: 4 additions & 1 deletion samcli/local/docker/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,13 @@ def create(self):
# Ex: 128m => 128MB
kwargs["mem_limit"] = "{}m".format(self._memory_limit_mb)

if self.network_id == 'host':
kwargs["network_mode"] = self.network_id

real_container = self.docker_client.containers.create(self._image, **kwargs)
self.id = real_container.id

if self.network_id:
if self.network_id and self.network_id != 'host':
network = self.docker_client.networks.get(self.network_id)
network.connect(self.id)

Expand Down
2 changes: 1 addition & 1 deletion samcli/local/init/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ def __init__(self, **kwargs):

class GenerateProjectFailedError(InitErrorException):
fmt = \
("An error ocurred while generating this {project}: {provider_error}")
("An error occurred while generating this {project}: {provider_error}")
Original file line number Diff line number Diff line change
@@ -1 +1 @@
requests==2.18.4
requests==2.20.0
2 changes: 1 addition & 1 deletion tests/functional/local/apigw/test_local_apigw_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ def make_service(list_of_routes, function_provider, cwd):

def make_service_response(port, method, scheme, resourcePath, resolvedResourcePath, pathParameters=None,
body=None, headers=None, queryParams=None, isBase64Encoded=False):
response_str = '{"httpMethod": "GET", "body": null, "resource": "/something/{event}", "requestContext": {"resourceId": "123456", "apiId": "1234567890", "resourcePath": "/something/{event}", "httpMethod": "GET", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "accountId": "123456789012", "stage": "prod", "identity": {"apiKey": null, "userArn": null, "cognitoAuthenticationType": null, "caller": null, "userAgent": "Custom User Agent String", "user": null, "cognitoIdentityPoolId": null, "cognitoAuthenticationProvider": null, "sourceIp": "127.0.0.1", "accountId": null}, "extendedRequestId": null, "path": "/something/{event}"}, "queryStringParameters": null, "headers": {"Host": "0.0.0.0:33651", "User-Agent": "python-requests/2.19.0", "Accept-Encoding": "gzip, deflate", "Accept": "*/*", "Connection": "keep-alive"}, "pathParameters": {"event": "event1"}, "stageVariables": null, "path": "/something/event1", "isBase64Encoded": false}' # NOQA
response_str = '{"httpMethod": "GET", "body": null, "resource": "/something/{event}", "requestContext": {"resourceId": "123456", "apiId": "1234567890", "resourcePath": "/something/{event}", "httpMethod": "GET", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "accountId": "123456789012", "stage": "prod", "identity": {"apiKey": null, "userArn": null, "cognitoAuthenticationType": null, "caller": null, "userAgent": "Custom User Agent String", "user": null, "cognitoIdentityPoolId": null, "cognitoAuthenticationProvider": null, "sourceIp": "127.0.0.1", "accountId": null}, "extendedRequestId": null, "path": "/something/{event}"}, "queryStringParameters": null, "headers": {"Host": "0.0.0.0:33651", "User-Agent": "python-requests/2.20.0", "Accept-Encoding": "gzip, deflate", "Accept": "*/*", "Connection": "keep-alive"}, "pathParameters": {"event": "event1"}, "stageVariables": null, "path": "/something/event1", "isBase64Encoded": false}' # NOQA
response = json.loads(response_str)

if body:
Expand Down
5 changes: 4 additions & 1 deletion tests/integration/local/invoke/invoke_integ_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def base_command(cls):
return command

def get_command_list(self, function_to_invoke, template_path=None, event_path=None, env_var_path=None,
parameter_overrides=None, region=None):
parameter_overrides=None, region=None, docker_network=None):
command_list = [self.cmd, "local", "invoke", function_to_invoke]

if template_path:
Expand All @@ -41,6 +41,9 @@ def get_command_list(self, function_to_invoke, template_path=None, event_path=No
if env_var_path:
command_list = command_list + ["-n", env_var_path]

if docker_network:
command_list = command_list + ["--docker-network", docker_network]

if parameter_overrides:
arg_value = " ".join([
"ParameterKey={},ParameterValue={}".format(key, value) for key, value in parameter_overrides.items()
Expand Down
11 changes: 11 additions & 0 deletions tests/integration/local/invoke/test_integrations_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,14 @@ def test_invoke_with_env_using_parameters_with_custom_region(self):
environ = json.loads(process_stdout.decode('utf-8'))

self.assertEquals(environ["Region"], custom_region)

def test_invoke_with_docker_network_of_host(self):
command_list = self.get_command_list("HelloWorldServerlessFunction",
template_path=self.template_path,
event_path=self.event_path,
docker_network='host')

process = Popen(command_list, stdout=PIPE)
return_code = process.wait()

self.assertEquals(return_code, 0)
16 changes: 12 additions & 4 deletions tests/unit/local/apigw/test_local_apigw_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,9 @@ def setUp(self):
self.request_mock.method = "GET"
self.request_mock.remote_addr = "190.0.0.0"
self.request_mock.get_data.return_value = b"DATA!!!!"
self.request_mock.args = {"query": ["params"]}
query_param_args_mock = Mock()
query_param_args_mock.lists.return_value = {"query": ["params"]}.items()
self.request_mock.args = query_param_args_mock
self.request_mock.headers = {"Content-Type": "application/json", "X-Test": "Value"}
self.request_mock.view_args = {"path": "params"}
self.request_mock.scheme = "http"
Expand Down Expand Up @@ -433,21 +435,27 @@ def test_construct_event_with_binary_data(self, should_base64_encode_patch):

def test_query_string_params_with_empty_params(self):
request_mock = Mock()
request_mock.args = {}
query_param_args_mock = Mock()
query_param_args_mock.lists.return_value = {}.items()
request_mock.args = query_param_args_mock

actual_query_string = LocalApigwService._query_string_params(request_mock)
self.assertEquals(actual_query_string, {})

def test_query_string_params_with_param_value_being_empty_list(self):
request_mock = Mock()
request_mock.args = {"param": []}
query_param_args_mock = Mock()
query_param_args_mock.lists.return_value = {"param": []}.items()
request_mock.args = query_param_args_mock

actual_query_string = LocalApigwService._query_string_params(request_mock)
self.assertEquals(actual_query_string, {"param": ""})

def test_query_string_params_with_param_value_being_non_empty_list(self):
request_mock = Mock()
request_mock.args = {"param": ["a", "b"]}
query_param_args_mock = Mock()
query_param_args_mock.lists.return_value = {"param": ["a", "b"]}.items()
request_mock.args = query_param_args_mock

actual_query_string = LocalApigwService._query_string_params(request_mock)
self.assertEquals(actual_query_string, {"param": "b"})
Expand Down
55 changes: 55 additions & 0 deletions tests/unit/local/docker/test_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ def test_must_connect_to_network_on_create(self):
Create a container with only required values. Optional values are not provided
:return:
"""
expected_volumes = {
self.host_dir: {
"bind": self.working_dir,
"mode": "ro"
}
}

network_id = "some id"
generated_id = "fooobar"
Expand All @@ -240,9 +246,58 @@ def test_must_connect_to_network_on_create(self):
container_id = container.create()
self.assertEquals(container_id, generated_id)

self.mock_docker_client.containers.create.assert_called_with(self.image,
command=self.cmd,
working_dir=self.working_dir,
tty=False,
volumes=expected_volumes
)

self.mock_docker_client.networks.get.assert_called_with(network_id)
network_mock.connect.assert_called_with(container_id)

def test_must_connect_to_host_network_on_create(self):
"""
Create a container with only required values. Optional values are not provided
:return:
"""
expected_volumes = {
self.host_dir: {
"bind": self.working_dir,
"mode": "ro"
}
}

network_id = "host"
generated_id = "fooobar"
self.mock_docker_client.containers.create.return_value = Mock()
self.mock_docker_client.containers.create.return_value.id = generated_id

network_mock = Mock()
self.mock_docker_client.networks.get.return_value = network_mock
network_mock.connect = Mock()

container = Container(self.image,
self.cmd,
self.working_dir,
self.host_dir,
docker_client=self.mock_docker_client)

container.network_id = network_id

container_id = container.create()
self.assertEquals(container_id, generated_id)

self.mock_docker_client.containers.create.assert_called_with(self.image,
command=self.cmd,
working_dir=self.working_dir,
tty=False,
volumes=expected_volumes,
network_mode='host'
)

self.mock_docker_client.networks.get.assert_not_called()

def test_must_fail_if_already_created(self):

container = Container(self.image,
Expand Down