From adafeb4f6ead405302fe186598e8d2c11ebc3241 Mon Sep 17 00:00:00 2001 From: Jacob Fuss Date: Tue, 12 Feb 2019 09:45:58 -0800 Subject: [PATCH 1/2] refactor(build): Move workflow config information into its own file --- samcli/commands/build/command.py | 4 +- samcli/lib/build/app_builder.py | 35 +--------- samcli/lib/build/workflow_config.py | 68 +++++++++++++++++++ .../integration/buildcmd/build_integ_base.py | 10 ++- tests/integration/buildcmd/test_build_cmd.py | 19 ------ tests/unit/commands/buildcmd/test_command.py | 3 +- .../unit/lib/build_module/test_app_builder.py | 49 ++----------- .../lib/build_module/test_workflow_config.py | 62 +++++++++++++++++ 8 files changed, 150 insertions(+), 100 deletions(-) create mode 100644 samcli/lib/build/workflow_config.py create mode 100644 tests/unit/lib/build_module/test_workflow_config.py diff --git a/samcli/commands/build/command.py b/samcli/commands/build/command.py index 0911732627..ef94b13248 100644 --- a/samcli/commands/build/command.py +++ b/samcli/commands/build/command.py @@ -11,8 +11,8 @@ from samcli.commands._utils.options import template_option_without_build, docker_common_options, \ parameter_override_option from samcli.commands.build.build_context import BuildContext -from samcli.lib.build.app_builder import ApplicationBuilder, UnsupportedRuntimeException, \ - BuildError, UnsupportedBuilderLibraryVersionError +from samcli.lib.build.app_builder import ApplicationBuilder, BuildError, UnsupportedBuilderLibraryVersionError +from samcli.lib.build.workflow_config import UnsupportedRuntimeException from samcli.commands._utils.template import move_template LOG = logging.getLogger(__name__) diff --git a/samcli/lib/build/app_builder.py b/samcli/lib/build/app_builder.py index 689835ec6e..38be88d8d4 100644 --- a/samcli/lib/build/app_builder.py +++ b/samcli/lib/build/app_builder.py @@ -6,7 +6,6 @@ import io import json import logging -from collections import namedtuple try: import pathlib @@ -20,15 +19,12 @@ from aws_lambda_builders.builder import LambdaBuilder from aws_lambda_builders.exceptions import LambdaBuilderError from aws_lambda_builders import RPC_PROTOCOL_VERSION as lambda_builders_protocol_version +from .workflow_config import get_workflow_config LOG = logging.getLogger(__name__) -class UnsupportedRuntimeException(Exception): - pass - - class UnsupportedBuilderLibraryVersionError(Exception): def __init__(self, container_name, error_msg): @@ -41,32 +37,6 @@ class BuildError(Exception): pass -def _get_workflow_config(runtime): - - config = namedtuple('Capability', ["language", "dependency_manager", "application_framework", "manifest_name"]) - - if runtime.startswith("python"): - return config( - language="python", - dependency_manager="pip", - application_framework=None, - manifest_name="requirements.txt") - elif runtime.startswith("nodejs"): - return config( - language="nodejs", - dependency_manager="npm", - application_framework=None, - manifest_name="package.json") - elif runtime.startswith("ruby"): - return config( - language="ruby", - dependency_manager="bundler", - application_framework=None, - manifest_name="Gemfile") - else: - raise UnsupportedRuntimeException("'{}' runtime is not supported".format(runtime)) - - class ApplicationBuilder(object): """ Class to build an entire application. Currently, this class builds Lambda functions only, but there is nothing that @@ -174,8 +144,7 @@ def update_template(self, template_dict, original_template_path, built_artifacts return template_dict def _build_function(self, function_name, codeuri, runtime): - - config = _get_workflow_config(runtime) + config = get_workflow_config(runtime) # Create the arguments to pass to the builder diff --git a/samcli/lib/build/workflow_config.py b/samcli/lib/build/workflow_config.py new file mode 100644 index 0000000000..e34d6921ca --- /dev/null +++ b/samcli/lib/build/workflow_config.py @@ -0,0 +1,68 @@ +""" +Contains Builder Workflow Configs for different Runtimes +""" + +from collections import namedtuple + + +CONFIG = namedtuple('Capability', ["language", "dependency_manager", "application_framework", "manifest_name"]) + +GO_MOD_CONFIG = CONFIG( + language="go", + dependency_manager="modules", + application_framework=None, + manifest_name="go.mod") + +PYTHON_PIP_CONFIG = CONFIG( + language="python", + dependency_manager="pip", + application_framework=None, + manifest_name="requirements.txt") + +NODEJS_NPM_CONFIG = CONFIG( + language="nodejs", + dependency_manager="npm", + application_framework=None, + manifest_name="package.json") + +RUBY_BUNDLER_CONFIG = CONFIG( + language="ruby", + dependency_manager="bundler", + application_framework=None, + manifest_name="Gemfile") + + +class UnsupportedRuntimeException(Exception): + pass + + +def get_workflow_config(runtime): + """ + Get a workflow config that corresponds to the runtime provided + + Parameters + ---------- + runtime str + The runtime of the config + + Returns + ------- + namedtuple(Capability) + namedtuple that represents the Builder Workflow Config + """ + + workflow_config_by_runtime = { + "go1.x": GO_MOD_CONFIG, + "python2.7": PYTHON_PIP_CONFIG, + "python3.6": PYTHON_PIP_CONFIG, + "python3.7": PYTHON_PIP_CONFIG, + "nodejs4.3": NODEJS_NPM_CONFIG, + "nodejs6.10": NODEJS_NPM_CONFIG, + "nodejs8.10": NODEJS_NPM_CONFIG, + "ruby2.5": RUBY_BUNDLER_CONFIG + } + + try: + return workflow_config_by_runtime[runtime] + except KeyError: + raise UnsupportedRuntimeException("'{}' runtime is not supported".format(runtime)) diff --git a/tests/integration/buildcmd/build_integ_base.py b/tests/integration/buildcmd/build_integ_base.py index d9031d3389..0882762087 100644 --- a/tests/integration/buildcmd/build_integ_base.py +++ b/tests/integration/buildcmd/build_integ_base.py @@ -1,6 +1,7 @@ import os import shutil import tempfile +from unittest import TestCase import docker @@ -9,7 +10,8 @@ except ImportError: from pathlib2 import Path -from unittest import TestCase + +from samcli.yamlhelper import yaml_parse class BuildIntegBase(TestCase): @@ -85,3 +87,9 @@ def _make_parameter_override_arg(self, overrides): return " ".join([ "ParameterKey={},ParameterValue={}".format(key, value) for key, value in overrides.items() ]) + + def _verify_resource_property(self, template_path, logical_id, property, expected_value): + + with open(template_path, 'r') as fp: + template_dict = yaml_parse(fp.read()) + self.assertEquals(expected_value, template_dict["Resources"][logical_id]["Properties"][property]) diff --git a/tests/integration/buildcmd/test_build_cmd.py b/tests/integration/buildcmd/test_build_cmd.py index 2397e63dfe..2416b302ec 100644 --- a/tests/integration/buildcmd/test_build_cmd.py +++ b/tests/integration/buildcmd/test_build_cmd.py @@ -10,7 +10,6 @@ from pathlib2 import Path from parameterized import parameterized -from samcli.yamlhelper import yaml_parse from .build_integ_base import BuildIntegBase @@ -105,12 +104,6 @@ def _verify_built_artifact(self, build_dir, function_logical_id, expected_files) actual_files = all_artifacts.intersection(expected_files) self.assertEquals(actual_files, expected_files) - def _verify_resource_property(self, template_path, logical_id, property, expected_value): - - with open(template_path, 'r') as fp: - template_dict = yaml_parse(fp.read()) - self.assertEquals(expected_value, template_dict["Resources"][logical_id]["Properties"][property]) - def _get_python_version(self): return "python{}.{}".format(sys.version_info.major, sys.version_info.minor) @@ -193,12 +186,6 @@ def _verify_built_artifact(self, build_dir, function_logical_id, expected_files, actual_files = all_modules.intersection(expected_modules) self.assertEquals(actual_files, expected_modules) - def _verify_resource_property(self, template_path, logical_id, property, expected_value): - - with open(template_path, 'r') as fp: - template_dict = yaml_parse(fp.read()) - self.assertEquals(expected_value, template_dict["Resources"][logical_id]["Properties"][property]) - class TestBuildCommand_RubyFunctions(BuildIntegBase): @@ -265,9 +252,3 @@ def _verify_built_artifact(self, build_dir, function_logical_id, expected_files, gem_path = ruby_bundled_path.joinpath(ruby_version[0], 'gems') self.assertTrue(any([True if self.EXPECTED_RUBY_GEM in gem else False for gem in os.listdir(str(gem_path))])) - - def _verify_resource_property(self, template_path, logical_id, property, expected_value): - - with open(template_path, 'r') as fp: - template_dict = yaml_parse(fp.read()) - self.assertEquals(expected_value, template_dict["Resources"][logical_id]["Properties"][property]) diff --git a/tests/unit/commands/buildcmd/test_command.py b/tests/unit/commands/buildcmd/test_command.py index 3c6700fb6d..00e1b2c112 100644 --- a/tests/unit/commands/buildcmd/test_command.py +++ b/tests/unit/commands/buildcmd/test_command.py @@ -5,7 +5,8 @@ from samcli.commands.build.command import do_cli from samcli.commands.exceptions import UserException -from samcli.lib.build.app_builder import UnsupportedRuntimeException, BuildError, UnsupportedBuilderLibraryVersionError +from samcli.lib.build.app_builder import BuildError, UnsupportedBuilderLibraryVersionError +from samcli.lib.build.workflow_config import UnsupportedRuntimeException class TestDoCli(TestCase): diff --git a/tests/unit/lib/build_module/test_app_builder.py b/tests/unit/lib/build_module/test_app_builder.py index 0229f4787d..2eb23dbd1c 100644 --- a/tests/unit/lib/build_module/test_app_builder.py +++ b/tests/unit/lib/build_module/test_app_builder.py @@ -5,52 +5,12 @@ from unittest import TestCase from mock import Mock, call, patch -from parameterized import parameterized -from samcli.lib.build.app_builder import ApplicationBuilder, _get_workflow_config,\ - UnsupportedBuilderLibraryVersionError, UnsupportedRuntimeException, BuildError, \ +from samcli.lib.build.app_builder import ApplicationBuilder,\ + UnsupportedBuilderLibraryVersionError, BuildError, \ LambdaBuilderError -class Test_get_workflow_config(TestCase): - - @parameterized.expand([ - ("python2.7", ), - ("python3.6", ) - ]) - def test_must_work_for_python(self, runtime): - - result = _get_workflow_config(runtime) - self.assertEquals(result.language, "python") - self.assertEquals(result.dependency_manager, "pip") - self.assertEquals(result.application_framework, None) - self.assertEquals(result.manifest_name, "requirements.txt") - - @parameterized.expand([ - ("nodejs6.10", ), - ("nodejs8.10", ), - ("nodejsX.Y", ), - ("nodejs", ) - ]) - def test_must_work_for_nodejs(self, runtime): - - result = _get_workflow_config(runtime) - self.assertEquals(result.language, "nodejs") - self.assertEquals(result.dependency_manager, "npm") - self.assertEquals(result.application_framework, None) - self.assertEquals(result.manifest_name, "package.json") - - def test_must_raise_for_unsupported_runtimes(self): - - runtime = "foobar" - - with self.assertRaises(UnsupportedRuntimeException) as ctx: - _get_workflow_config(runtime) - - self.assertEquals(str(ctx.exception), - "'foobar' runtime is not supported") - - class TestApplicationBuilder_build(TestCase): def setUp(self): @@ -158,7 +118,7 @@ def setUp(self): "/build/dir", "/base/dir") - @patch("samcli.lib.build.app_builder._get_workflow_config") + @patch("samcli.lib.build.app_builder.get_workflow_config") @patch("samcli.lib.build.app_builder.osutils") def test_must_build_in_process(self, osutils_mock, get_workflow_config_mock): function_name = "function_name" @@ -186,7 +146,7 @@ def test_must_build_in_process(self, osutils_mock, get_workflow_config_mock): manifest_path, runtime) - @patch("samcli.lib.build.app_builder._get_workflow_config") + @patch("samcli.lib.build.app_builder.get_workflow_config") @patch("samcli.lib.build.app_builder.osutils") def test_must_build_in_container(self, osutils_mock, get_workflow_config_mock): function_name = "function_name" @@ -252,6 +212,7 @@ def test_must_raise_on_error(self, lambda_builder_mock): config_mock = Mock() builder_instance_mock = lambda_builder_mock.return_value = Mock() builder_instance_mock.build.side_effect = LambdaBuilderError() + self.builder._get_build_options = Mock(return_value=None) with self.assertRaises(BuildError): self.builder._build_function_in_process(config_mock, diff --git a/tests/unit/lib/build_module/test_workflow_config.py b/tests/unit/lib/build_module/test_workflow_config.py new file mode 100644 index 0000000000..2eae1c98fd --- /dev/null +++ b/tests/unit/lib/build_module/test_workflow_config.py @@ -0,0 +1,62 @@ +from unittest import TestCase +from parameterized import parameterized + +from samcli.lib.build.workflow_config import get_workflow_config, UnsupportedRuntimeException + + +class Test_get_workflow_config(TestCase): + + @parameterized.expand([ + ("python2.7", ), + ("python3.6", ) + ]) + def test_must_work_for_python(self, runtime): + + result = get_workflow_config(runtime) + self.assertEquals(result.language, "python") + self.assertEquals(result.dependency_manager, "pip") + self.assertEquals(result.application_framework, None) + self.assertEquals(result.manifest_name, "requirements.txt") + + @parameterized.expand([ + ("nodejs4.3", ), + ("nodejs6.10", ), + ("nodejs8.10", ), + ]) + def test_must_work_for_nodejs(self, runtime): + + result = get_workflow_config(runtime) + self.assertEquals(result.language, "nodejs") + self.assertEquals(result.dependency_manager, "npm") + self.assertEquals(result.application_framework, None) + self.assertEquals(result.manifest_name, "package.json") + + @parameterized.expand([ + ("ruby2.5", ) + ]) + def test_must_work_for_ruby(self, runtime): + result = get_workflow_config(runtime) + self.assertEquals(result.language, "ruby") + self.assertEquals(result.dependency_manager, "bundler") + self.assertEquals(result.application_framework, None) + self.assertEquals(result.manifest_name, "Gemfile") + + @parameterized.expand([ + ("go1.x", ) + ]) + def test_must_work_for_go(self, runtime): + result = get_workflow_config(runtime) + self.assertEquals(result.language, "go") + self.assertEquals(result.dependency_manager, "modules") + self.assertEquals(result.application_framework, None) + self.assertEquals(result.manifest_name, "go.mod") + + def test_must_raise_for_unsupported_runtimes(self): + + runtime = "foobar" + + with self.assertRaises(UnsupportedRuntimeException) as ctx: + get_workflow_config(runtime) + + self.assertEquals(str(ctx.exception), + "'foobar' runtime is not supported") From f9eac7193bbfb9f5acea9a1466d186a41a321cf4 Mon Sep 17 00:00:00 2001 From: Jacob Fuss Date: Tue, 12 Feb 2019 12:31:25 -0800 Subject: [PATCH 2/2] Remove go for workflow config --- samcli/lib/build/workflow_config.py | 7 ------- tests/unit/lib/build_module/test_workflow_config.py | 10 ---------- 2 files changed, 17 deletions(-) diff --git a/samcli/lib/build/workflow_config.py b/samcli/lib/build/workflow_config.py index e34d6921ca..54d49c77df 100644 --- a/samcli/lib/build/workflow_config.py +++ b/samcli/lib/build/workflow_config.py @@ -7,12 +7,6 @@ CONFIG = namedtuple('Capability', ["language", "dependency_manager", "application_framework", "manifest_name"]) -GO_MOD_CONFIG = CONFIG( - language="go", - dependency_manager="modules", - application_framework=None, - manifest_name="go.mod") - PYTHON_PIP_CONFIG = CONFIG( language="python", dependency_manager="pip", @@ -52,7 +46,6 @@ def get_workflow_config(runtime): """ workflow_config_by_runtime = { - "go1.x": GO_MOD_CONFIG, "python2.7": PYTHON_PIP_CONFIG, "python3.6": PYTHON_PIP_CONFIG, "python3.7": PYTHON_PIP_CONFIG, diff --git a/tests/unit/lib/build_module/test_workflow_config.py b/tests/unit/lib/build_module/test_workflow_config.py index 2eae1c98fd..45c90f322f 100644 --- a/tests/unit/lib/build_module/test_workflow_config.py +++ b/tests/unit/lib/build_module/test_workflow_config.py @@ -41,16 +41,6 @@ def test_must_work_for_ruby(self, runtime): self.assertEquals(result.application_framework, None) self.assertEquals(result.manifest_name, "Gemfile") - @parameterized.expand([ - ("go1.x", ) - ]) - def test_must_work_for_go(self, runtime): - result = get_workflow_config(runtime) - self.assertEquals(result.language, "go") - self.assertEquals(result.dependency_manager, "modules") - self.assertEquals(result.application_framework, None) - self.assertEquals(result.manifest_name, "go.mod") - def test_must_raise_for_unsupported_runtimes(self): runtime = "foobar"