Skip to content

Commit

Permalink
terraform package, chalice variables, cli engine help
Browse files Browse the repository at this point in the history
  • Loading branch information
kapilt committed Aug 6, 2019
1 parent f2295d5 commit 3e2aadb
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 17 deletions.
15 changes: 10 additions & 5 deletions chalice/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,22 +368,27 @@ def generate_sdk(ctx, sdk_type, stage, outdir):


@cli.command('package')
@click.option('--pkg-format', default='cloudformation',
help=('Specify the provisioning engine to use for '
'template output. Chalice supports both '
'CloudFormation and Terraform. Default '
'is CloudFormation.'),
type=click.Choice(['cloudformation', 'terraform']))
@click.option('--stage', default=DEFAULT_STAGE_NAME,
help="Chalice Stage to package.")
@click.option('--single-file', is_flag=True,
default=False,
help=("Create a single packaged file. "
"By default, the 'out' argument "
"specifies a directory in which the "
"package assets will be placed. If "
"this argument is specified, a single "
"zip file will be created instead."))
@click.option('--stage', default=DEFAULT_STAGE_NAME)
@click.option('--pkg-format', default='cloudformation',
type=click.Choice(['cloudformation', 'terraform']))
"zip file will be created instead. CloudFormation Only."))
@click.option('--merge-template',
help=('Specify a JSON template to be merged '
'into the generated template. This is useful '
'for adding resources to a Chalice template or '
'modify values in the template.'))
'modify values in the template. CloudFormation Only.'))
@click.argument('out')
@click.pass_context
def package(ctx, single_file, stage, merge_template,
Expand Down
30 changes: 26 additions & 4 deletions chalice/package.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# pylint: disable=too-many-lines
import json
import os
import copy
Expand Down Expand Up @@ -35,11 +36,11 @@ def create_app_packager(
osutils=osutils,
merger=TemplateDeepMerger(),
merge_template=merge_template)])
generator = SAMTemplateGenerator()
generator = SAMTemplateGenerator(config)
else:
build_stage = create_build_stage(
osutils, ui, TerraformSwaggerGenerator())
generator = TerraformGenerator()
generator = TerraformGenerator(config)
post_processors.append(
TerraformCodeLocationPostProcessor(osutils=osutils))

Expand Down Expand Up @@ -85,6 +86,10 @@ class TemplateGenerator(object):

template_file = None # type: str

def __init__(self, config):
# type: (Config) -> None
self._config = config

def dispatch(self, resource, template):
# type: (models.Model, Dict[str, Any]) -> None
name = '_generate_%s' % resource.__class__.__name__.lower()
Expand Down Expand Up @@ -127,8 +132,9 @@ class SAMTemplateGenerator(TemplateGenerator):

template_file = "sam.json"

def __init__(self):
# type: () -> None
def __init__(self, config):
# type: (Config) -> None
super(SAMTemplateGenerator, self).__init__(config)
self._seen_names = set([]) # type: Set[str]

def generate(self, resources):
Expand Down Expand Up @@ -577,6 +583,18 @@ def generate(self, resources):
'terraform': {
'required_version': '> 0.11.0'
},
'variable': {
'chalice_app_name': {
'type': 'string',
'description': 'Chalice App Name (not editable)',
'default': self._config.app_name
},
'chalice_stage_name': {
'type': 'string',
'description': 'Chalice Stage (not editable)',
'default': self._config.chalice_stage,
}
},
'provider': {
'aws': {'version': '> 2.0.0'},
},
Expand All @@ -585,6 +603,7 @@ def generate(self, resources):
'aws_region': {'chalice': {}}
}
}

for resource in resources:
self.dispatch(resource, template)
return template
Expand Down Expand Up @@ -806,6 +825,9 @@ def _generate_restapi(self, resource, template):
template['resource'].setdefault('aws_api_gateway_deployment', {})[
resource.resource_name] = {
'stage_name': resource.api_gateway_stage,
# Ensure that the deployment gets redeployed if we update
# the swagger description for the api by using its checksum
# in the stage description.
'stage_description': (
"${md5(data.template_file.chalice_api_swagger.rendered)}"),
'rest_api_id': '${aws_api_gateway_rest_api.%s.id}' % (
Expand Down
13 changes: 9 additions & 4 deletions docs/source/topics/tf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ command.

When you run this command, chalice will generate the AWS Lambda
deployment package that contains your application and a `Terraform
<https://terraform.io>`__ configuration file. You can then use the
<https://www.terraform.io>`__ configuration file. You can then use the
terraform cli to deploy your chalice application.

Considerations
Expand Down Expand Up @@ -72,9 +72,14 @@ command created a directory that contained two files, a
``deployment.zip`` file, which is the Lambda deployment package, and a
``chalice.tf.json`` file, which is the Terraform template that can be
deployed using Terraform. Next we're going to use the Terraform CLI
to deploy our app. Note terraform will deploy run against all terraform
files in this directory, so we can add additional resources for our
application by adding terraform additional files here.
to deploy our app.

Note terraform will deploy run against all terraform files in this
directory, so we can add additional resources for our application by
adding terraform additional files here. The Chalice terraform template
includes two variables that we can optionally use when constructing
these additional resources `chalice_stage_name` and
`chalice_app_name`, these variables should **not** be user overridden.

First let's run Terraform init to install the AWS Terraform Provider::

Expand Down
34 changes: 30 additions & 4 deletions tests/unit/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def test_terraform_post_processor_moves_files_once():


def test_template_generator_default():
tgen = package.TemplateGenerator()
tgen = package.TemplateGenerator(Config())

with pytest.raises(package.UnsupportedFeatureError):
tgen.dispatch(models.Model(), {})
Expand Down Expand Up @@ -220,12 +220,12 @@ def setup_method(self):
deps_builder=DependencyBuilder(),
build_stage=mock.Mock(spec=BuildStage)
)
self.template_gen = self.template_gen_factory()
self.template_gen = self.template_gen_factory(Config())

def generate_template(self, config, chalice_stage_name):
resources = self.resource_builder.construct_resources(
config, chalice_stage_name)
return self.template_gen.generate(resources)
return self.template_gen_factory(config).generate(resources)

def lambda_function(self):
return models.LambdaFunction(
Expand Down Expand Up @@ -283,7 +283,7 @@ def generate_template(self, config, chalice_stage_name):
elif isinstance(r, models.FileBasedIAMPolicy):
r.document = self.EmptyPolicy

return self.template_gen.generate(resources)
return self.template_gen_factory(config).generate(resources)

def get_function(self, template):
functions = list(template['resource'][
Expand Down Expand Up @@ -384,6 +384,14 @@ def test_can_generate_rest_api(self, sample_app_with_auth):
assert resources['aws_api_gateway_rest_api'][
'rest_api']['endpoint_configuration'] == {'types': ['PRIVATE']}

assert 'aws_api_gateway_stage' not in resources
assert resources['aws_api_gateway_deployment']['rest_api'] == {
'rest_api_id': '${aws_api_gateway_rest_api.rest_api.id}',
'stage_description': (
'${md5(data.template_file.chalice_api_swagger.rendered)}'),
'stage_name': 'api'
}

# We should also create the auth lambda function.
assert 'myauth' in resources['aws_lambda_function']

Expand Down Expand Up @@ -424,6 +432,24 @@ def handler(event):
}]
}

def test_can_generate_chalice_terraform_variables(self, sample_app):
config = Config.create(chalice_app=sample_app,
project_dir='.',
app_name='myfoo',
api_gateway_stage='dev')

template = self.generate_template(config, 'dev')
assert template['variable'] == {
'chalice_app_name': {
'default': 'myfoo',
'description': 'Chalice App Name (not editable)',
'type': 'string'},
'chalice_stage_name': {
'default': 'dev',
'description': 'Chalice Stage (not editable)',
'type': 'string'}
}

def test_can_package_s3_event_handler_sans_filters(self, sample_app):
@sample_app.on_s3_event(bucket='foo')
def handler(event):
Expand Down

0 comments on commit 3e2aadb

Please sign in to comment.