Skip to content

Commit

Permalink
Merge branch 'upstream' into terraform-package
Browse files Browse the repository at this point in the history
  • Loading branch information
kapilt committed Jun 20, 2019
2 parents 8fbd4b1 + 4853c6c commit 373d2f3
Show file tree
Hide file tree
Showing 24 changed files with 279 additions and 27 deletions.
8 changes: 8 additions & 0 deletions .dependabot/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 1
update_configs:
- package_manager: python
directory: ./
update_schedule: daily
allowed_updates:
- match:
dependency_name: "pip"
16 changes: 14 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
CHANGELOG
=========

Next Release (TBD)
==================
1.9.0
=====

* Update PIP to support up to 19.1.x
(`#1104 <https://github.com/aws/chalice/issues/1104>`__)
Expand All @@ -19,6 +19,18 @@ Next Release (TBD)
(`#1131 <https://github.com/aws/chalice/issues/1131>`__)
* Add layer support to chalice package
(`#1130 <https://github.com/aws/chalice/issues/1130>`__)
* Fix bug with route ``name`` kwarg raising a ``TypeError``
(`#1112 <https://github.com/aws/chalice/issues/1112>`__)
* Change exceptions to always be logged at the ERROR level
(`#969 <https://github.com/aws/chalice/issues/969>`__)
* Fix bug handling exceptions during ``chalice invoke`` on
Python 3.7
(`#1139 <https://github.com/aws/chalice/issues/1139>`__)
* Add support for API Gateway compression
(`#672 <https://github.com/aws/chalice/issues/672>`__)
* Add support for both relative and absolute paths for
``--package-dir``
(`#940 <https://github.com/aws/chalice/issues/940>`__)


1.8.0
Expand Down
10 changes: 5 additions & 5 deletions chalice/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from collections import defaultdict


__version__ = '1.8.0'
__version__ = '1.9.0'
_PARAMS = re.compile(r'{\w+}')

# Implementation note: This file is intended to be a standalone file
Expand Down Expand Up @@ -540,7 +540,7 @@ def schedule(self, expression, name=None):
def route(self, path, **kwargs):
return self._create_registration_function(
handler_type='route',
name=kwargs.get('name'),
name=kwargs.pop('name', None),
# This looks a little weird taking kwargs as a key,
# but we want to preserve keep the **kwargs signature
# in the route decorator.
Expand Down Expand Up @@ -907,12 +907,12 @@ def _get_view_function_response(self, view_function, function_args):
status_code=e.STATUS_CODE)
except Exception:
headers = {}
self.log.error("Caught exception for %s", view_function,
exc_info=True)
if self.debug:
# If the user has turned on debug mode,
# we'll let the original exception propogate so
# we'll let the original exception propagate so
# they get more information about what went wrong.
self.log.debug("Caught exception for %s", view_function,
exc_info=True)
stack_trace = ''.join(traceback.format_exc())
body = stack_trace
headers['Content-Type'] = 'text/plain'
Expand Down
8 changes: 8 additions & 0 deletions chalice/awsclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,14 @@ def update_api_from_swagger(self, rest_api_id, swagger_document):
mode='overwrite',
body=json.dumps(swagger_document, indent=2))

def update_rest_api(self, rest_api_id, patch_operations):
# type: (str, List[Dict]) -> None
client = self._client('apigateway')
client.update_rest_api(
restApiId=rest_api_id,
patchOperations=patch_operations
)

def delete_rest_api(self, rest_api_id):
# type: (str) -> None
client = self._client('apigateway')
Expand Down
5 changes: 4 additions & 1 deletion chalice/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ def get_system_info():
message='%(prog)s %(version)s, {}'
.format(get_system_info()))
@click.option('--project-dir',
help='The project directory. Defaults to CWD')
help='The project directory path (absolute or relative).'
'Defaults to CWD')
@click.option('--debug/--no-debug',
default=False,
help='Print debug logs to stderr.')
Expand All @@ -100,6 +101,8 @@ def cli(ctx, project_dir, debug=False):
# type: (click.Context, str, bool) -> None
if project_dir is None:
project_dir = os.getcwd()
elif not os.path.isabs(project_dir):
project_dir = os.path.abspath(project_dir)
if debug is True:
_configure_logging(logging.DEBUG)
ctx.obj['project_dir'] = project_dir
Expand Down
6 changes: 6 additions & 0 deletions chalice/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@ def api_gateway_stage(self):
return self._chain_lookup('api_gateway_stage',
varies_per_chalice_stage=True)

@property
def minimum_compression_size(self):
# type: () -> int
return self._chain_lookup('minimum_compression_size',
varies_per_chalice_stage=True)

@property
def iam_policy_file(self):
# type: () -> str
Expand Down
2 changes: 2 additions & 0 deletions chalice/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def index():
# in the config module.
DEFAULT_HANDLER_NAME = 'api_handler'

MIN_COMPRESSION_SIZE = 0
MAX_COMPRESSION_SIZE = 10485760

LAMBDA_TRUST_POLICY = {
"Version": "2012-10-17",
Expand Down
39 changes: 28 additions & 11 deletions chalice/deploy/deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,35 @@

from chalice import app
from chalice.config import Config # noqa
from chalice.config import DeployedResources # noqa
from chalice.compat import is_broken_pipe_error
from chalice.awsclient import DeploymentPackageTooLargeError, TypedAWSClient
from chalice.awsclient import LambdaClientError, AWSClientError
from chalice.constants import MAX_LAMBDA_DEPLOYMENT_SIZE, VPC_ATTACH_POLICY, \
DEFAULT_LAMBDA_TIMEOUT, DEFAULT_LAMBDA_MEMORY_SIZE, LAMBDA_TRUST_POLICY, \
SQS_EVENT_SOURCE_POLICY
from chalice.awsclient import DeploymentPackageTooLargeError
from chalice.awsclient import LambdaClientError
from chalice.awsclient import AWSClientError
from chalice.awsclient import TypedAWSClient
from chalice.constants import MAX_LAMBDA_DEPLOYMENT_SIZE
from chalice.constants import VPC_ATTACH_POLICY
from chalice.constants import DEFAULT_LAMBDA_TIMEOUT
from chalice.constants import DEFAULT_LAMBDA_MEMORY_SIZE
from chalice.constants import LAMBDA_TRUST_POLICY
from chalice.constants import SQS_EVENT_SOURCE_POLICY
from chalice.deploy import models
from chalice.deploy.executor import Executor
from chalice.deploy.packager import PipRunner, SubprocessPip, \
DependencyBuilder as PipDependencyBuilder, LambdaDeploymentPackager
from chalice.deploy.planner import PlanStage, RemoteState, \
ResourceSweeper, NoopPlanner
from chalice.deploy.packager import PipRunner
from chalice.deploy.packager import SubprocessPip
from chalice.deploy.packager import DependencyBuilder as PipDependencyBuilder
from chalice.deploy.packager import LambdaDeploymentPackager
from chalice.deploy.planner import PlanStage
from chalice.deploy.planner import RemoteState
from chalice.deploy.planner import ResourceSweeper
from chalice.deploy.planner import NoopPlanner
from chalice.deploy.swagger import TemplatedSwaggerGenerator
from chalice.deploy.swagger import SwaggerGenerator # noqa
from chalice.policy import AppPolicyGenerator
from chalice.utils import OSUtils, UI, serialize_to_json
from chalice.deploy.validate import validate_configuration
from chalice.policy import AppPolicyGenerator
from chalice.utils import OSUtils
from chalice.utils import UI
from chalice.utils import serialize_to_json


OptStr = Optional[str]
Expand Down Expand Up @@ -432,6 +444,10 @@ def _create_rest_api_model(self,
# it's just <app>-<stage>.
function_name = '%s-%s' % (config.app_name, config.chalice_stage)
lambda_function.function_name = function_name
if config.minimum_compression_size is None:
minimum_compression = ''
else:
minimum_compression = str(config.minimum_compression_size)
authorizers = []
for auth in config.chalice_app.builtin_auth_handlers:
auth_lambda = self._create_lambda_model(
Expand All @@ -442,6 +458,7 @@ def _create_rest_api_model(self,
return models.RestAPI(
resource_name='rest_api',
swagger_doc=models.Placeholder.BUILD_STAGE,
minimum_compression=minimum_compression,
api_gateway_stage=config.api_gateway_stage,
lambda_function=lambda_function,
authorizers=authorizers,
Expand Down
1 change: 1 addition & 0 deletions chalice/deploy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ def dependencies(self):
class RestAPI(ManagedModel):
resource_type = 'rest_api'
swagger_doc = attrib() # type: DV[Dict[str, Any]]
minimum_compression = attrib() # type: str
api_gateway_stage = attrib() # type: str
lambda_function = attrib() # type: LambdaFunction
authorizers = attrib(default=Factory(list)) # type: List[LambdaFunction]
Expand Down
11 changes: 11 additions & 0 deletions chalice/deploy/planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,17 @@ def _plan_restapi(self, resource):
# at the end of deploying a rest API that apply to both
# the update and create case.
shared_plan_epilogue = [
models.APICall(
method_name='update_rest_api',
params={
'rest_api_id': Variable('rest_api_id'),
'patch_operations': [{
'op': 'replace',
'path': '/minimumCompressionSize',
'value': resource.minimum_compression,
}],
},
),
models.APICall(
method_name='add_permission_for_apigateway',
params={'function_name': function_name,
Expand Down
16 changes: 16 additions & 0 deletions chalice/deploy/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from chalice import app # noqa
from chalice.config import Config # noqa
from chalice.constants import EXPERIMENTAL_ERROR_MSG
from chalice.constants import MIN_COMPRESSION_SIZE
from chalice.constants import MAX_COMPRESSION_SIZE


class ExperimentalFeatureError(Exception):
Expand Down Expand Up @@ -38,6 +40,7 @@ def validate_configuration(config):
routes = config.chalice_app.routes
validate_routes(routes)
validate_route_content_types(routes, config.chalice_app.api.binary_types)
validate_minimum_compression_size(config)
_validate_manage_iam_role(config)
validate_python_version(config)
validate_unique_function_names(config)
Expand Down Expand Up @@ -146,6 +149,19 @@ def _validate_cors_for_route(route_url, route_methods):
)


def validate_minimum_compression_size(config):
# type: (Config) -> None
if config.minimum_compression_size is None:
return
if not isinstance(config.minimum_compression_size, int):
raise ValueError("'minimum_compression_size' must be an int.")
elif config.minimum_compression_size < MIN_COMPRESSION_SIZE \
or config.minimum_compression_size > MAX_COMPRESSION_SIZE:
raise ValueError("'minimum_compression_size' must be equal to or "
"greater than %s and less than or equal to %s."
% (MIN_COMPRESSION_SIZE, MAX_COMPRESSION_SIZE))


def _validate_manage_iam_role(config):
# type: (Config) -> None
# We need to check if manage_iam_role is None because that's the value
Expand Down
5 changes: 5 additions & 0 deletions chalice/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ def _generate_restapi(self, resource, template):
'DefinitionBody': resource.swagger_doc,
}
}
if resource.minimum_compression:
properties = resources['RestAPI']['Properties']
properties['MinimumCompressionSize'] = \
int(resource.minimum_compression)

handler_cfn_name = to_cfn_resource_name(
resource.lambda_function.resource_name)
api_handler = template['Resources'].pop(handler_cfn_name)
Expand Down
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@
# built documents.
#
# The short X.Y version.
version = u'1.8'
version = u'1.9'
# The full version, including alpha/beta/rc tags.
release = u'1.8.0'
release = u'1.9.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
7 changes: 7 additions & 0 deletions docs/source/topics/configfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ be checked.
will also be the URL prefix for your API
(``https://endpoint/prefix/your-api``).

* ``minimum_compression_size`` - An integer value that indicates
the minimum compression size to apply to the API gateway. If
this key is specified in both a stage specific config option
as well as a top level key, the stage specific key will
override the top level key for the given stage. For more information
check out the `Service Docs <https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-gzip-compression-decompression.html>`__

* ``manage_iam_role`` - ``true``/``false``. Indicates if you
want chalice to create and update the IAM role
used for your application. By default, this value is ``true``.
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

setup(
name='chalice',
version='1.8.0',
version='1.9.0',
description="Microframework",
long_description=README,
author="James Saryerwinnie",
Expand Down
21 changes: 21 additions & 0 deletions tests/functional/cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,24 @@ def test_error_message_displayed_when_missing_feature_opt_in(runner):
result = _run_cli_command(runner, cli.package, ['out'])
assert isinstance(result.exception, ExperimentalFeatureError)
assert 'MYTESTFEATURE' in str(result.exception)


@pytest.mark.parametrize(
"path",
[
None,
'.',
os.getcwd,
],
)
def test_cli_with_absolute_path(runner, path):
with runner.isolated_filesystem():
if callable(path):
path = path()
result = runner.invoke(
cli.cli,
['--project-dir', path, 'new-project', 'testproject'],
obj={})
assert result.exit_code == 0
assert os.listdir(os.getcwd()) == ['testproject']
assert_chalice_app_structure_created(dirname='testproject')
17 changes: 17 additions & 0 deletions tests/functional/test_awsclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,23 @@ def test_update_api_from_swagger(stubbed_session):
stubbed_session.verify_stubs()


def test_update_rest_api(stubbed_session):
apig = stubbed_session.stub('apigateway')
patch_operations = [{'op': 'replace',
'path': '/minimumCompressionSize',
'value': '2'}]
apig.update_rest_api(
restApiId='rest_api_id',
patchOperations=patch_operations).returns({})

stubbed_session.activate_stubs()
awsclient = TypedAWSClient(stubbed_session)

awsclient.update_rest_api('rest_api_id',
patch_operations)
stubbed_session.verify_stubs()


def test_can_get_or_create_rule_arn(stubbed_session):
events = stubbed_session.stub('events')
events.put_rule(
Expand Down
1 change: 1 addition & 0 deletions tests/unit/deploy/test_deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,7 @@ def test_can_generate_swagger_builder(self):
rest_api = models.RestAPI(
resource_name='foo',
swagger_doc=models.Placeholder.BUILD_STAGE,
minimum_compression='',
api_gateway_stage='api',
lambda_function=None,
)
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/deploy/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def test_can_default_to_no_auths_in_rest_api(lambda_function):
rest_api = models.RestAPI(
resource_name='rest_api',
swagger_doc={'swagger': '2.0'},
minimum_compression='',
api_gateway_stage='api',
lambda_function=lambda_function,
)
Expand All @@ -51,6 +52,7 @@ def test_can_add_authorizers_to_dependencies(lambda_function):
rest_api = models.RestAPI(
resource_name='rest_api',
swagger_doc={'swagger': '2.0'},
minimum_compression='',
api_gateway_stage='api',
lambda_function=lambda_function,
authorizers=[auth1, auth2],
Expand Down
Loading

0 comments on commit 373d2f3

Please sign in to comment.