Skip to content

Commit

Permalink
refactor(build): Move workflow config information into its own file (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jfuss authored Feb 12, 2019
1 parent 4b88618 commit 1cc7810
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 100 deletions.
4 changes: 2 additions & 2 deletions samcli/commands/build/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
35 changes: 2 additions & 33 deletions samcli/lib/build/app_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import io
import json
import logging
from collections import namedtuple

try:
import pathlib
Expand All @@ -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):
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
61 changes: 61 additions & 0 deletions samcli/lib/build/workflow_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Contains Builder Workflow Configs for different Runtimes
"""

from collections import namedtuple


CONFIG = namedtuple('Capability', ["language", "dependency_manager", "application_framework", "manifest_name"])

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 = {
"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))
10 changes: 9 additions & 1 deletion tests/integration/buildcmd/build_integ_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import shutil
import tempfile
from unittest import TestCase

import docker

Expand All @@ -9,7 +10,8 @@
except ImportError:
from pathlib2 import Path

from unittest import TestCase

from samcli.yamlhelper import yaml_parse


class BuildIntegBase(TestCase):
Expand Down Expand Up @@ -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])
19 changes: 0 additions & 19 deletions tests/integration/buildcmd/test_build_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from pathlib2 import Path
from parameterized import parameterized

from samcli.yamlhelper import yaml_parse
from .build_integ_base import BuildIntegBase


Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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):

Expand Down Expand Up @@ -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])
3 changes: 2 additions & 1 deletion tests/unit/commands/buildcmd/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
49 changes: 5 additions & 44 deletions tests/unit/lib/build_module/test_app_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down
52 changes: 52 additions & 0 deletions tests/unit/lib/build_module/test_workflow_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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")

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")

0 comments on commit 1cc7810

Please sign in to comment.