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

v0.21.0 #1374

Merged
merged 11 commits into from
Aug 27, 2019
Merged

v0.21.0 #1374

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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func-test:
@echo Telemetry Status: $(SAM_CLI_TELEMETRY)
pytest --cov samcli.local --cov samcli.commands.local --cov-report term-missing tests/functional

smoke-test:
# Smoke tests run in parallel
pytest -n 4 tests/functional

flake:
# Make sure code conforms to PEP8 standards
flake8 samcli
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The AWS Serverless Application Model (SAM) is an open-source framework for build
It provides shorthand syntax to express functions, APIs, databases, and event source mappings.
With just a few lines of configuration, you can define the application you want and model it.

[![Getting Started with AWS SAM](./docs/get-started-youtube.png)](https://www.youtube.com/watch?v=1dzihtC5LJ0)
-[![Getting Started with AWS SAM](./media/get-started-youtube.png)](https://www.youtube.com/watch?v=1dzihtC5LJ0)

## Get Started

Expand Down
15 changes: 15 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ image:
- Ubuntu
- Visual Studio 2017

configuration:
- smoke

environment:
AWS_DEFAULT_REGION: us-east-1
SAM_CLI_DEV: 1
Expand All @@ -20,6 +23,7 @@ environment:
- PYTHON_HOME: "C:\\Python37-x64"
PYTHON_VERSION: '3.7.4'
PYTHON_ARCH: '64'
RUN_SMOKE: 1

for:
-
Expand Down Expand Up @@ -52,6 +56,14 @@ for:
- sh: "sudo unzip -d /opt/gradle /tmp/gradle-*.zip"
- sh: "PATH=/opt/gradle/gradle-5.5/bin:$PATH"

-
matrix:
only:
- ONLY_SMOKE: 1
test_script:
# Smoke tests run in parallel
- "pytest -n 4 -vv tests/smoke"

build_script:
- "python -c \"import sys; print(sys.executable)\""

Expand All @@ -67,3 +79,6 @@ test_script:
# Runs only in Linux
- sh: "pytest -vv tests/integration"

# Smoke tests run in parallel - it runs on both Linux & Windows
# Presence of the RUN_SMOKE envvar will run the smoke tests
- ps: "If ($env:RUN_SMOKE) {pytest -n 4 -vv tests/smoke}"
Binary file added media/get-started-youtube.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Flask~=1.0.2
boto3~=1.9, >=1.9.56
PyYAML~=5.1
cookiecutter~=1.6.0
aws-sam-translator==1.13.1
aws-sam-translator==1.11.0
docker~=4.0
dateparser~=0.7
python-dateutil~=2.6
pathlib2~=2.3.2; python_version<"3.4"
requests==2.22.0
serverlessrepo==0.1.9
aws_lambda_builders==0.3.0
aws_lambda_builders==0.4.0
3 changes: 2 additions & 1 deletion requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ astroid>=1.5.8,<2.1.0
pylint==1.7.2

# Test requirements
pytest==3.0.7
pytest==3.1.0
py==1.4.33
mock==2.0.0
parameterized==0.6.1
pathlib2==2.3.2; python_version<"3.4"
futures==3.2.0; python_version<"3.2.3"
# Py3.2 backport
backports.tempfile==1.0
pytest-xdist==1.20.0
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.20.0'
__version__ = '0.21.0'
19 changes: 11 additions & 8 deletions samcli/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@
import logging
import importlib
import sys
from collections import OrderedDict

import click

logger = logging.getLogger(__name__)

# Commands that are bundled with the CLI by default
_SAM_CLI_COMMAND_PACKAGES = {
"samcli.commands.local.local",
"samcli.commands.validate.validate",
# Commands that are bundled with the CLI by default in app life-cycle order.

_SAM_CLI_COMMAND_PACKAGES = [
"samcli.commands.init",
"samcli.commands.deploy",
"samcli.commands.validate.validate",
"samcli.commands.build",
"samcli.commands.local.local",
"samcli.commands.package",
"samcli.commands.deploy",
"samcli.commands.logs",
"samcli.commands.build",
"samcli.commands.publish"
}
]

DEPRECATION_NOTICE = (
"Warning : AWS SAM CLI will no longer support "
Expand Down Expand Up @@ -79,7 +82,7 @@ def _set_commands(package_names):
:return: Dictionary with command name as key and the package name as value.
"""

commands = {}
commands = OrderedDict()

for pkg_name in package_names:
cmd_name = pkg_name.split('.')[-1]
Expand Down
15 changes: 13 additions & 2 deletions samcli/commands/build/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,19 @@ def do_cli(function_identifier, # pylint: disable=too-many-locals

click.secho("\nBuild Succeeded", fg="green")

msg = gen_success_msg(os.path.relpath(ctx.build_dir),
os.path.relpath(ctx.output_template_path),
# try to use relpath so the command is easier to understand, however,
# under Windows, when SAM and (build_dir or output_template_path) are
# on different drive, relpath() fails.
try:
build_dir_in_success_message = os.path.relpath(ctx.build_dir)
output_template_path_in_success_message = os.path.relpath(ctx.output_template_path)
except ValueError:
LOG.debug("Failed to retrieve relpath - using the specified path as-is instead")
build_dir_in_success_message = ctx.build_dir
output_template_path_in_success_message = ctx.output_template_path

msg = gen_success_msg(build_dir_in_success_message,
output_template_path_in_success_message,
os.path.abspath(ctx.build_dir) == os.path.abspath(DEFAULT_BUILD_DIR))

click.secho(msg, fg="yellow")
Expand Down
4 changes: 3 additions & 1 deletion samcli/commands/init/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
LOG = logging.getLogger(__name__)


@click.command(context_settings=dict(help_option_names=[u'-h', u'--help']))
@click.command("init",
short_help="Init an AWS SAM application.",
context_settings=dict(help_option_names=[u'-h', u'--help']))
@click.option('-l', '--location', help="Template location (git, mercurial, http(s), zip, path)")
@click.option('-r', '--runtime', type=click.Choice(INIT_RUNTIMES), default=DEFAULT_RUNTIME,
help="Lambda Runtime of your app")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,29 @@
}
}
},
"connect": {
"contact-flow-event": {
"filename": "ConnectContactFlowEvent",
"help": "Generates an Amazon Connect Contact Flow Event",
"tags": {
"region": {
"default": "us-east-1"
},
"partition": {
"default": "aws"
},
"account-id": {
"default": "123456789012"
},
"contact-id": {
"default": "5ca32fbd-8f92-46af-92a5-6b0f970f0efe"
},
"phone-number": {
"default": "+11234567890"
}
}
}
},
"dynamodb": {
"update": {
"filename": "DynamoDBUpdate",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"Name": "ContactFlowEvent",
"Details": {
"ContactData": {
"Attributes": {},
"Channel": "VOICE",
"ContactId": "{{{contact_id}}}",
"CustomerEndpoint": {
"Address": "{{{phone_number}}}",
"Type": "TELEPHONE_NUMBER"
},
"InitialContactId": "{{{contact_id}}}",
"InitiationMethod": "API",
"InstanceARN": "arn:{{{partition}}}:connect:{{{region}}}:{{{account_id}}}:instance/9308c2a1-9bc6-4cea-8290-6c0b4a6d38fa",
"MediaStreams": {
"Customer": {
"Audio": {
"StartFragmentNumber": "91343852333181432392682062622220590765191907586",
"StartTimestamp": "1565781909613",
"StreamARN": "arn:{{{partition}}}:kinesisvideo:{{{region}}}:{{{account_id}}}:stream/connect-contact-a3d73b84-ce0e-479a-a9dc-5637c9d30ac9/1565272947806"
}
}
},
"PreviousContactId": "{{{contact_id}}}",
"Queue": null,
"SystemEndpoint": {
"Address": "{{{phone_number}}}",
"Type": "TELEPHONE_NUMBER"
}
},
"Parameters": {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,12 @@ def intrinsic_property_resolver(self, intrinsic, parent_function="template"):
"""
if intrinsic is None:
raise InvalidIntrinsicException("Missing Intrinsic property in {}".format(parent_function))
if any(isinstance(intrinsic, object_type) for object_type in [string_types, bool, int]) or intrinsic == {}:
return intrinsic
if isinstance(intrinsic, list):
return [self.intrinsic_property_resolver(item) for item in intrinsic]
if not isinstance(intrinsic, dict) or intrinsic == {}:
return intrinsic

# `intrinsic` is a dict at this point.

keys = list(intrinsic.keys())
key = keys[0]
Expand Down Expand Up @@ -720,7 +722,7 @@ def resolve_sub_attribute(intrinsic_item, symbol_resolver):
)
result = resolve_sub_attribute(sanitized_item, self._symbol_resolver)
sub_str = re.sub(
pattern=r"\$\{" + sub_item + r"\}", string=sub_str, repl=result
pattern=r"\$\{" + sub_item + r"\}", string=sub_str, repl=str(result)
)
return sub_str

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Resources:
CodeUri: HelloWorldFunction
Handler: helloworld.App::handleRequest
Runtime: java8
MemorySize: 512
Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
Variables:
PARAM1: VALUE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Resources:
CodeUri: HelloWorldFunction
Handler: helloworld.App::handleRequest
Runtime: java8
MemorySize: 512
Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
Variables:
PARAM1: VALUE
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/buildcmd/test_build_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ class TestBuildCommand_PythonFunctions(BuildIntegBase):
@parameterized.expand([
("python2.7", False),
("python3.6", False),
("python3.7", False),
("python2.7", "use_container"),
("python3.6", "use_container"),
("python3.7", "use_container"),
])
def test_with_default_requirements(self, runtime, use_container):

Expand Down
4 changes: 4 additions & 0 deletions tests/integration/publish/publish_app_integ_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import uuid
import shutil
import tempfile
import time
from unittest import TestCase

import boto3
Expand Down Expand Up @@ -47,6 +48,9 @@ def setUpClass(cls):
code_body = cls.test_data_path.joinpath("main.py").read_text(encoding="utf-8")
cls.s3_bucket.put_object(Key="main.py", Body=code_body)

# Given 3 seconds for all the bucket creation to complete
time.sleep(3)

@classmethod
def tearDownClass(cls):
cls.s3_bucket.delete_objects(Delete={
Expand Down
4 changes: 4 additions & 0 deletions tests/integration/publish/test_command_integ.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import time
import json
from subprocess import Popen, PIPE

Expand All @@ -25,6 +26,9 @@ def setUp(self):
response = self.sar_client.create_application(**app_metadata)
self.application_id = response['ApplicationId']

# Sleep for a little bit to make server happy
time.sleep(2)

def tearDown(self):
super(TestPublishExistingApp, self).tearDown()
# Delete application for each test
Expand Down
5 changes: 5 additions & 0 deletions tests/integration/testdata/invoke/runtimes/go1.x/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package main

import (
"time"

"github.com/aws/aws-lambda-go/lambda"
)

Expand All @@ -9,6 +11,9 @@ import (
// However you could use other event sources (S3, Kinesis etc), or JSON-decoded primitive types such as 'string'.
func Handler() (string, error) {

// Go functions finish too fast making the integ tests flaky. Adding 100ms sleep to make sure the Docker
// container response make it back to SAM CLI.
time.Sleep(100 * time.Millisecond)
return "Hello World", nil

}
Expand Down
Binary file modified tests/integration/testdata/invoke/runtimes/go1.x/main.zip
Binary file not shown.
Empty file added tests/smoke/__init__.py
Empty file.
61 changes: 61 additions & 0 deletions tests/smoke/download_sar_templates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import requests
import os
import logging
import time
import boto3


logging.basicConfig(level=logging.INFO)
LOG = logging.getLogger()
TEMPLATE_FOLDER = os.path.join("templates", "sar")


def download(count=100):

sar_browse_url = "https://shr32taah3.execute-api.us-east-1.amazonaws.com/Prod/applications/browse"
current_page = 1
retry_count = 0
apps = []

while len(apps) < count and retry_count < 10:
try:
response = requests.get(sar_browse_url, {
"pageSize": count if count < 10 else 10,
"pageNumber": current_page,
"includeAppsWithCapabilities": "CAPABILITY_IAM,CAPABILITY_NAMED_IAM,CAPABILITY_RESOURCE_POLICY,CAPABILITY_AUTO_EXPAND"
})

response.raise_for_status()
result = response.json()

# Successful request
apps = apps + result["applications"]
current_page += 1
retry_count = 0
except requests.exceptions.RequestException as ex:
LOG.warning("Got throttled by SAR", exc_info=ex)
retry_count += 1

for index, app in enumerate(apps):
app_id = app["id"]
name = app["name"]
template_file_name = os.path.join(TEMPLATE_FOLDER, name+"-template.yaml")
LOG.info("[%s/%s] %s", index, count, name)
_download_templates(app_id, template_file_name)
time.sleep(0.1) # 100ms aka 10 TPS

def _download_templates(app_id, template_file_path):
sar = boto3.client('serverlessrepo')
response = sar.get_application(ApplicationId=app_id)

template_url = response["Version"]["TemplateUrl"]

with open(template_file_path, "wb") as fp:
r = requests.get(template_url, stream=True)
for chunk in r.iter_content(chunk_size=128):
fp.write(chunk)

if __name__ == "__main__":
count = 100
LOG.info("Downloading %s templates", count)
download(count=count)
Loading