Skip to content

Commit

Permalink
feat: Adding a sam --info command (aws#776)
Browse files Browse the repository at this point in the history
This command currently prints version information in JSON format.
In future we will expand this to print everything from versions of
dependencies, list of commands available, capabilities exposed by
the commands, etc. Hopefully eventually this will provide a nice
list of machine readable instructions for other tools to integrate
with SAM CLI
  • Loading branch information
sanathkr authored Nov 19, 2018
1 parent 5cd2b67 commit 1b4453c
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 29 deletions.
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ docker>=3.3.0
dateparser~=0.7
python-dateutil~=2.6
pathlib2~=2.3.2; python_version<"3.4"
aws_lambda_builders==0.0.2-dev
aws_lambda_builders==0.0.2
13 changes: 13 additions & 0 deletions samcli/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import logging
import json
import click

from samcli import __version__
Expand Down Expand Up @@ -36,9 +37,21 @@ def aws_creds_options(f):
return f


def print_info(ctx, param, value):
if not value or ctx.resilient_parsing:
return

click.echo(json.dumps({
"version": __version__
}, indent=2))

ctx.exit()


@click.command(cls=BaseCommand)
@common_options
@click.version_option(version=__version__, prog_name="SAM CLI")
@click.option("--info", is_flag=True, is_eager=True, callback=print_info, expose_value=False)
@pass_context
def cli(ctx):
"""
Expand Down
61 changes: 42 additions & 19 deletions samcli/commands/build/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

LOG = logging.getLogger(__name__)

DEFAULT_BUILD_DIR = os.path.join(".aws-sam", "build")

HELP_TEXT = """
Use this command to build your AWS Lambda Functions source code to generate artifacts that can run on AWS Lambda.\n
Use this command to build your AWS Lambda Functions source code to generate artifacts that target AWS Lambda's
execution environment.\n
\b
Supported Resource Types
------------------------
Expand All @@ -31,10 +33,10 @@
1. Python2.7\n
2. Python3.6\n
\b
Usage
-----
In your SAM template, specify the path to your function's source code
in the resource's Code or CodeUri property.
Examples
--------
To use this command, update your SAM template to specify the path
to your function's source code in the resource's Code or CodeUri property.
\b
To build on your workstation, run this command in folder containing
SAM template. Built artifacts will be written to .aws-sam/build folder
Expand All @@ -47,24 +49,25 @@
$ sam build && sam local invoke
\b
To build and package for deployment
$ sam build && sam package
$ sam build && sam package --s3-bucket <bucketname>
"""


@click.command("build", help=HELP_TEXT, short_help="Build your Lambda function code")
@click.option('--build-dir', '-b',
default=os.path.join(".aws-sam", "build"),
default=DEFAULT_BUILD_DIR,
type=click.Path(file_okay=False, dir_okay=True, writable=True), # Must be a directory
help="Path to a folder where the built artifacts will be stored")
@click.option("--base-dir", "-s",
default=None,
type=click.Path(dir_okay=True, file_okay=False), # Must be a directory
help="Resolve relative paths to function's source code with respect to this folder. Use this if "
"SAM template and your source code are not in same enclosing folder. By default, relative paths to"
"SAM template and your source code are not in same enclosing folder. By default, relative paths "
"are resolved with respect to the SAM template's location")
@click.option("--use-container",
@click.option("--use-container", "-u",
is_flag=True,
help="Run the builds inside a Docker container that simulates an AWS Lambda like environment")
help="If your functions depend on packages that have natively compiled dependencies, use this flag "
"to build your function inside an AWS Lambda-like Docker container")
@click.option("--manifest", "-m",
default=None,
type=click.Path(),
Expand Down Expand Up @@ -133,19 +136,39 @@ def do_cli(template, # pylint: disable=too-many-locals
with open(ctx.output_template_path, "w") as fp:
fp.write(yaml_dump(modified_template))

msg = """\nBuild Artifacts Available At: {artifacts_dir}
Next Steps
==========
[*] Invoke Function: sam local invoke -t {template}
[*] Package: sam package --template-file {template}
""".format(artifacts_dir=os.path.relpath(ctx.build_dir),
template=os.path.relpath(ctx.output_template_path))

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

msg = gen_success_msg(os.path.relpath(ctx.build_dir),
os.path.relpath(ctx.output_template_path),
os.path.abspath(ctx.build_dir) == os.path.abspath(DEFAULT_BUILD_DIR))

click.secho(msg, fg="yellow")

except (UnsupportedRuntimeException, BuildError, UnsupportedBuilderLibraryVersionError) as ex:
click.secho("Build Failed", fg="red")
raise UserException(str(ex))


def gen_success_msg(artifacts_dir, output_template_path, is_default_build_dir):

invoke_cmd = "sam local invoke"
if not is_default_build_dir:
invoke_cmd += " -t {}".format(output_template_path)

package_cmd = "sam package --s3-bucket <yourbucket>"
if not is_default_build_dir:
package_cmd += " --template-file {}".format(output_template_path)

msg = """\nBuilt Artifacts : {artifacts_dir}
Built Template : {template}
Commands you can use next
=========================
[*] Invoke Function: {invokecmd}
[*] Package: {packagecmd}
""".format(invokecmd=invoke_cmd,
packagecmd=package_cmd,
artifacts_dir=artifacts_dir,
template=output_template_path)

return msg
12 changes: 6 additions & 6 deletions tests/integration/buildcmd/test_build_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@
class TestBuildCommand_PythonFunctions(BuildIntegBase):

EXPECTED_FILES_GLOBAL_MANIFEST = set()
EXPECTED_FILES_PROJECT_MANIFEST = {'__init__.py', 'main.py', 'numpy', 'cryptography', "jinja2",
EXPECTED_FILES_PROJECT_MANIFEST = {'__init__.py', 'main.py', 'numpy',
# 'cryptography',
"jinja2",
'requirements.txt'}

FUNCTION_LOGICAL_ID = "PythonFunction"

@parameterized.expand([
("python2.7", False),
("python3.6", False)
# FIXME: Turning off Container build tests until official Docker Container is published
# ("python2.7", "use_container"),
# ("python3.6", "use_container"),
("python3.6", False),
("python2.7", "use_container"),
("python3.6", "use_container"),
])
def test_with_default_requirements(self, runtime, use_container):

Expand Down
4 changes: 2 additions & 2 deletions tests/integration/testdata/buildcmd/Python/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import numpy
from cryptography.fernet import Fernet
# from cryptography.fernet import Fernet
from jinja2 import Template


def handler(event, context):

# Try using some of the modules to make sure they work & don't crash the process
print(Fernet.generate_key())
# print(Fernet.generate_key())

template = Template('Hello {{ name }}')

Expand Down
4 changes: 3 additions & 1 deletion tests/integration/testdata/buildcmd/Python/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# These are some hard packages to build. Using them here helps us verify that building works on various platforms

numpy~=1.15
cryptography~=2.4
# `cryptography` has a dependency on `pycparser` which, for some reason doesn't build inside a Docker container.
# Turning this off until we resolve this issue: https://github.com/awslabs/aws-lambda-builders/issues/29
# cryptography~=2.4
Jinja2~=2.10

0 comments on commit 1b4453c

Please sign in to comment.