コード例 #1
0
    def _build_function_in_process(self, config, source_dir, artifacts_dir,
                                   scratch_dir, manifest_path, runtime,
                                   options):

        builder = LambdaBuilder(
            language=config.language,
            dependency_manager=config.dependency_manager,
            application_framework=config.application_framework,
        )

        runtime = runtime.replace(".al2", "")

        try:
            builder.build(
                source_dir,
                artifacts_dir,
                scratch_dir,
                manifest_path,
                runtime=runtime,
                executable_search_paths=config.executable_search_paths,
                mode=self._mode,
                options=options,
            )
        except LambdaBuilderError as ex:
            raise BuildError(wrapped_from=ex.__class__.__name__,
                             msg=str(ex)) from ex

        return artifacts_dir
コード例 #2
0
    def setUp(self):
        self.source_dir = self.TEST_DATA_FOLDER
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.manifest_path_valid = os.path.join(self.TEST_DATA_FOLDER,
                                                "requirements-numpy.txt")
        self.manifest_path_invalid = os.path.join(self.TEST_DATA_FOLDER,
                                                  "requirements-invalid.txt")

        self.test_data_files = {
            "__init__.py", "main.py", "requirements-invalid.txt",
            "requirements-numpy.txt"
        }

        self.builder = LambdaBuilder(language="python",
                                     dependency_manager="pip",
                                     application_framework=None)
        self.runtime = "{language}{major}.{minor}".format(
            language=self.builder.capability.language,
            major=sys.version_info.major,
            minor=sys.version_info.minor)
        self.runtime_mismatch = {
            "python3.6": "python2.7",
            "python3.7": "python2.7",
            "python2.7": "python3.8",
            "python3.8": "python2.7",
        }
コード例 #3
0
class TestDotnetDep(TestCase):
    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.builder = LambdaBuilder(language="dotnet",
                                     dependency_manager="cli-package",
                                     application_framework=None)

        self.runtime = "dotnetcore2.1"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_with_defaults_file(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "WithDefaultsFile")

        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           source_dir,
                           runtime=self.runtime)

        expected_files = {
            "Amazon.Lambda.Core.dll", "Amazon.Lambda.Serialization.Json.dll",
            "Newtonsoft.Json.dll", "WithDefaultsFile.deps.json",
            "WithDefaultsFile.dll", "WithDefaultsFile.pdb",
            "WithDefaultsFile.runtimeconfig.json"
        }

        output_files = set(os.listdir(self.artifacts_dir))

        self.assertEquals(expected_files, output_files)

    def test_require_parameters(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "RequireParameters")

        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           source_dir,
                           runtime=self.runtime,
                           options={
                               "--framework": "netcoreapp2.1",
                               "--configuration": "Debug"
                           })

        expected_files = {
            "Amazon.Lambda.Core.dll", "Amazon.Lambda.Serialization.Json.dll",
            "Newtonsoft.Json.dll", "RequireParameters.deps.json",
            "RequireParameters.dll", "RequireParameters.pdb",
            "RequireParameters.runtimeconfig.json"
        }

        output_files = set(os.listdir(self.artifacts_dir))

        self.assertEquals(expected_files, output_files)
コード例 #4
0
    def test_with_mocks(self, get_workflow_mock, importlib_mock):
        workflow_cls = Mock()
        workflow_instance = workflow_cls.return_value = Mock()

        get_workflow_mock.return_value = workflow_cls

        with patch.object(LambdaBuilder, "_validate_runtime"):
            builder = LambdaBuilder(self.lang,
                                    self.lang_framework,
                                    self.app_framework,
                                    supported_workflows=[])

            builder.build("source_dir",
                          "artifacts_dir",
                          "scratch_dir",
                          "manifest_path",
                          runtime="runtime",
                          optimizations="optimizations",
                          options="options")

            workflow_cls.assert_called_with("source_dir",
                                            "artifacts_dir",
                                            "scratch_dir",
                                            "manifest_path",
                                            runtime="runtime",
                                            optimizations="optimizations",
                                            options="options")
            workflow_instance.run.assert_called_once()
コード例 #5
0
 def setUp(self):
     self.artifacts_dir = tempfile.mkdtemp()
     self.scratch_dir = tempfile.mkdtemp()
     self.builder = LambdaBuilder(language='java',
                                  dependency_manager='gradle',
                                  application_framework=None)
     self.runtime = 'java11'
コード例 #6
0
def build_lambda(source_dir, output_dir, runtime, archive_name):
    """
    Build a Lambda Function zip using a builder from aws-lambda-builders
    :param source_dir: Source Directory
    :param output_dir: Output Directory
    :param runtime: Lambda Runtime
    :param archive_name: Archive name (optional)
    :return: Path to generated zip file
    """
    config = get_config(runtime, source_dir)
    builder = LambdaBuilder(config.language, config.dependency_manager, None)
    manifest_path = os.path.join(source_dir, config.manifest_name)
    archive_name = archive_name if archive_name else os.path.basename(os.path.normpath(source_dir))

    info(f'\nBuilding {runtime} Lambda function from {source_dir}\n')

    with tempfile.TemporaryDirectory() as artifacts_dir:
        with tempfile.TemporaryDirectory() as scratch_dir:
            try:
                builder.build(source_dir, artifacts_dir, scratch_dir, manifest_path, runtime)
                zip_file = make_archive(os.path.join(output_dir, archive_name), 'zip', artifacts_dir)
                info(f'\nBuilt Lambda Archive {zip_file}')
                return zip_file
            except LambdaBuilderError as e:
                raise PackagingError(e)
コード例 #7
0
 def setUp(self):
     self.artifacts_dir = tempfile.mkdtemp()
     self.scratch_dir = tempfile.mkdtemp()
     self.builder = LambdaBuilder(language="go",
                                  dependency_manager="modules",
                                  application_framework=None)
     self.runtime = "go1.x"
コード例 #8
0
 def setUp(self):
     self.artifacts_dir = tempfile.mkdtemp()
     self.scratch_dir = tempfile.mkdtemp()
     self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
     self.builder = LambdaBuilder(language="ruby",
                                  dependency_manager="bundler",
                                  application_framework=None)
     self.runtime = "ruby2.5"
コード例 #9
0
    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()
        self.dependencies_dir = tempfile.mkdtemp()

        self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "no-deps")

        self.builder = LambdaBuilder(language="nodejs", dependency_manager="npm", application_framework=None)
コード例 #10
0
    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.builder = LambdaBuilder(language="dotnet",
                                     dependency_manager="cli-package",
                                     application_framework=None)

        self.runtime = "dotnetcore2.1"
コード例 #11
0
    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        os.environ["GOPATH"] = self.TEST_DATA_FOLDER

        self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "src", "nodeps")

        self.builder = LambdaBuilder(language="go", dependency_manager="dep", application_framework=None)

        self.runtime = "go1.x"
コード例 #12
0
class TestBuilderWithHelloWorkflow(TestCase):

    HELLO_WORKFLOW_MODULE = "hello_workflow.write_hello"
    TEST_WORKFLOWS_FOLDER = os.path.join(os.path.dirname(__file__), "testdata",
                                         "workflows")

    def setUp(self):
        # Temporarily add the testdata folder to PYTHOHNPATH
        sys.path.append(self.TEST_WORKFLOWS_FOLDER)

        self.source_dir = tempfile.mkdtemp()
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = os.path.join(tempfile.mkdtemp(), "scratch")
        self.hello_builder = LambdaBuilder(
            language="python",
            dependency_manager="test",
            application_framework="test",
            supported_workflows=[self.HELLO_WORKFLOW_MODULE],
        )

        # The builder should write a file called hello.txt with contents "Hello World"
        self.expected_filename = os.path.join(self.artifacts_dir, "hello.txt")
        self.expected_contents = "Hello World"

    def tearDown(self):
        self.hello_builder._clear_workflows()
        shutil.rmtree(self.source_dir)
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

        # Remove the workflows folder from PYTHONPATH
        sys.path.remove(self.TEST_WORKFLOWS_FOLDER)

    def test_run_hello_workflow_with_exec_paths(self):

        self.hello_builder.build(
            self.source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            "/ignored",
            "python3.8",
            executable_search_paths=[str(pathlib.Path(sys.executable).parent)],
        )

        self.assertTrue(os.path.exists(self.expected_filename))
        contents = ""
        with open(self.expected_filename, "r") as fp:
            contents = fp.read()

        self.assertEqual(contents, self.expected_contents)
コード例 #13
0
    def setUp(self):
        # Temporarily add the testdata folder to PYTHOHNPATH
        sys.path.append(self.TEST_WORKFLOWS_FOLDER)

        self.source_dir = tempfile.mkdtemp()
        self.artifacts_dir = tempfile.mkdtemp()
        self.hello_builder = LambdaBuilder(
            language="test",
            dependency_manager="test",
            application_framework="test",
            supported_workflows=[self.HELLO_WORKFLOW_MODULE])

        # The builder should write a file called hello.txt with contents "Hello World"
        self.expected_filename = os.path.join(self.artifacts_dir, 'hello.txt')
        self.expected_contents = "Hello World"
コード例 #14
0
    def test_with_real_workflow_class(self):
        """Define a real workflow class and try to fetch it. This ensures the workflow registration actually works.
        """

        # Declare my test workflow.
        class MyWorkflow(BaseWorkflow):
            NAME = "MyWorkflow"
            CAPABILITY = Capability(language=self.lang,
                                    dependency_manager=self.lang_framework,
                                    application_framework=self.app_framework)

            def __init__(self,
                         source_dir,
                         artifacts_dir,
                         scratch_dir,
                         manifest_path,
                         runtime=None,
                         optimizations=None,
                         options=None):
                super(MyWorkflow, self).__init__(source_dir,
                                                 artifacts_dir,
                                                 scratch_dir,
                                                 manifest_path,
                                                 runtime=runtime,
                                                 optimizations=optimizations,
                                                 options=options)

        # Don't load any other workflows. The above class declaration will automatically load the workflow into registry
        builder = LambdaBuilder(self.lang,
                                self.lang_framework,
                                self.app_framework,
                                supported_workflows=[])

        # Make sure this workflow is selected
        self.assertEqual(builder.selected_workflow_cls, MyWorkflow)
コード例 #15
0
    def setUp(self):
        self.source_dir = self.TEST_DATA_FOLDER
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.manifest_path_valid = os.path.join(self.TEST_DATA_FOLDER,
                                                "Makefile")

        self.test_data_files = {
            "__init__.py", "main.py", "requirements-requests.txt"
        }

        self.builder = LambdaBuilder(language="provided",
                                     dependency_manager=None,
                                     application_framework=None)
        self.runtime = "provided"
コード例 #16
0
class TestRubyWorkflow(TestCase):
    """
    Verifies that `ruby` workflow works by building a Lambda using Bundler
    """

    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()
        self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
        self.builder = LambdaBuilder(language="ruby", dependency_manager="bundler", application_framework=None)
        self.runtime = "ruby2.5"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_builds_project_without_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
        self.builder.build(
            source_dir, self.artifacts_dir, self.scratch_dir, os.path.join(source_dir, "Gemfile"), runtime=self.runtime
        )
        expected_files = {"handler.rb", "Gemfile", "Gemfile.lock", ".bundle", "vendor"}
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEqual(expected_files, output_files)

    def test_builds_project_with_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "with-deps")
        self.builder.build(
            source_dir, self.artifacts_dir, self.scratch_dir, os.path.join(source_dir, "Gemfile"), runtime=self.runtime
        )
        expected_files = {"handler.rb", "Gemfile", "Gemfile.lock", ".bundle", "vendor"}
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEqual(expected_files, output_files)

    def test_builds_project_and_ignores_excluded_files(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "excluded-files")
        self.builder.build(
            source_dir, self.artifacts_dir, self.scratch_dir, os.path.join(source_dir, "Gemfile"), runtime=self.runtime
        )
        expected_files = {"handler.rb", "Gemfile", "Gemfile.lock", ".bundle", "vendor"}
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEqual(expected_files, output_files)

    def test_fails_if_bundler_cannot_resolve_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "broken-deps")
        with self.assertRaises(WorkflowFailedError) as ctx:
            self.builder.build(
                source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                os.path.join(source_dir, "Gemfile"),
                runtime=self.runtime,
            )
        self.assertIn("RubyBundlerBuilder:RubyBundle - Bundler Failed: ", str(ctx.exception))
コード例 #17
0
    def test_must_not_load_any_workflows(self, get_workflow_mock, importlib_mock):

        modules = []  # Load no modules
        builder = LambdaBuilder(self.lang, self.lang_framework, self.app_framework, supported_workflows=modules)

        self.assertEqual(builder.supported_workflows, [])

        # Make sure the modules are loaded in same order as passed
        importlib_mock.import_module.assert_not_called()
コード例 #18
0
ファイル: app_builder.py プロジェクト: raviitsoft/aws-sam-cli
    def _build_function_in_process(self, config, source_dir, artifacts_dir,
                                   scratch_dir, manifest_path, runtime):

        builder = LambdaBuilder(
            language=config.language,
            dependency_manager=config.dependency_manager,
            application_framework=config.application_framework)

        try:
            builder.build(source_dir,
                          artifacts_dir,
                          scratch_dir,
                          manifest_path,
                          runtime=runtime)
        except LambdaBuilderError as ex:
            raise BuildError(str(ex))

        return artifacts_dir
コード例 #19
0
    def test_with_mocks(self, scratch_dir_exists, get_workflow_mock,
                        importlib_mock, os_mock):
        workflow_cls = Mock()
        workflow_instance = workflow_cls.return_value = Mock()

        os_mock.path.exists.return_value = scratch_dir_exists

        get_workflow_mock.return_value = workflow_cls

        builder = LambdaBuilder(self.lang,
                                self.lang_framework,
                                self.app_framework,
                                supported_workflows=[])

        builder.build(
            "source_dir",
            "artifacts_dir",
            "scratch_dir",
            "manifest_path",
            runtime="runtime",
            optimizations="optimizations",
            options="options",
            executable_search_paths="executable_search_paths",
            mode=None,
        )

        workflow_cls.assert_called_with(
            "source_dir",
            "artifacts_dir",
            "scratch_dir",
            "manifest_path",
            runtime="runtime",
            optimizations="optimizations",
            options="options",
            executable_search_paths="executable_search_paths",
            mode=None,
        )
        workflow_instance.run.assert_called_once()
        os_mock.path.exists.assert_called_once_with("scratch_dir")
        if scratch_dir_exists:
            os_mock.makedirs.not_called()
        else:
            os_mock.makedirs.assert_called_once_with("scratch_dir")
コード例 #20
0
    def test_must_support_loading_custom_workflows(self, get_workflow_mock, importlib_mock):

        modules = ["a.b.c", "c.d", "e.f", "z.k"]

        # instantiate
        builder = LambdaBuilder(self.lang, self.lang_framework, self.app_framework, supported_workflows=modules)

        self.assertEqual(builder.supported_workflows, modules)

        # Make sure the modules are loaded in same order as passed
        importlib_mock.import_module.assert_has_calls([call(m) for m in modules], any_order=False)
コード例 #21
0
class TestGoWorkflow(TestCase):
    """
    Verifies that `go` workflow works by building a Lambda using Go Modules
    """

    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()
        self.builder = LambdaBuilder(language="go", dependency_manager="modules", application_framework=None)
        self.runtime = "go1.x"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_builds_project_without_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")
        self.builder.build(
            source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            os.path.join(source_dir, "go.mod"),
            runtime=self.runtime,
            options={"artifact_executable_name": "no-deps-main"},
        )
        expected_files = {"no-deps-main"}
        output_files = set(os.listdir(self.artifacts_dir))
        print(output_files)
        self.assertEqual(expected_files, output_files)

    def test_builds_project_with_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "with-deps")
        self.builder.build(
            source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            os.path.join(source_dir, "go.mod"),
            runtime=self.runtime,
            options={"artifact_executable_name": "with-deps-main"},
        )
        expected_files = {"with-deps-main"}
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEqual(expected_files, output_files)

    def test_fails_if_modules_cannot_resolve_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "broken-deps")
        with self.assertRaises(WorkflowFailedError) as ctx:
            self.builder.build(
                source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                os.path.join(source_dir, "go.mod"),
                runtime=self.runtime,
                options={"artifact_executable_name": "failed"},
            )
        self.assertIn("GoModulesBuilder:Build - Builder Failed: ", str(ctx.exception))
コード例 #22
0
class TestJavaMaven(TestCase):
    SINGLE_BUILD_TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "testdata", "single-build")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()
        self.builder = LambdaBuilder(language="java", dependency_manager="maven", application_framework=None)
        self.runtime = "java8"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_build_single_build_with_deps_resources_exclude_test_jars(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, "with-deps")
        manifest_path = os.path.join(source_dir, "pom.xml")
        self.builder.build(source_dir, self.artifacts_dir, self.scratch_dir, manifest_path, runtime=self.runtime)
        expected_files = [
            p("aws", "lambdabuilders", "Main.class"),
            p("some_data.txt"),
            p("lib", "software.amazon.awssdk.annotations-2.1.0.jar"),
        ]
        self.assert_artifact_contains_files(expected_files)
        self.assert_artifact_not_contains_file(p("lib", "junit-4.12.jar"))
        self.assert_src_dir_not_touched(source_dir)

    def test_build_single_build_no_deps(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, "no-deps")
        manifest_path = os.path.join(source_dir, "pom.xml")
        self.builder.build(source_dir, self.artifacts_dir, self.scratch_dir, manifest_path, runtime=self.runtime)
        expected_files = [p("aws", "lambdabuilders", "Main.class"), p("some_data.txt")]
        self.assert_artifact_contains_files(expected_files)
        self.assert_artifact_not_contains_file(p("lib"))
        self.assert_src_dir_not_touched(source_dir)

    def test_build_single_build_with_deps_broken(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, "with-deps-broken")
        manifest_path = os.path.join(source_dir, "pom.xml")
        with self.assertRaises(WorkflowFailedError) as raised:
            self.builder.build(source_dir, self.artifacts_dir, self.scratch_dir, manifest_path, runtime=self.runtime)
        self.assertTrue(raised.exception.args[0].startswith("JavaMavenWorkflow:MavenBuild - Maven Failed"))
        self.assert_src_dir_not_touched(source_dir)

    def assert_artifact_contains_files(self, files):
        for f in files:
            self.assert_artifact_contains_file(f)

    def assert_artifact_contains_file(self, p):
        self.assertTrue(os.path.exists(os.path.join(self.artifacts_dir, p)))

    def assert_artifact_not_contains_file(self, p):
        self.assertFalse(os.path.exists(os.path.join(self.artifacts_dir, p)))

    def assert_src_dir_not_touched(self, source_dir):
        self.assertFalse(os.path.exists(os.path.join(source_dir, "target")))
コード例 #23
0
    def test_must_load_all_default_workflows(self, get_workflow_mock, importlib_mock):

        # instantiate
        builder = LambdaBuilder(self.lang, self.lang_framework, self.app_framework)

        self.assertEqual(builder.supported_workflows, [self.DEFAULT_WORKFLOW_MODULE])

        # First check if the module was loaded
        importlib_mock.import_module.assert_called_once_with(self.DEFAULT_WORKFLOW_MODULE)

        # then check if we tried to get a workflow for given capability
        get_workflow_mock.assert_called_with(
            Capability(
                language=self.lang, dependency_manager=self.lang_framework, application_framework=self.app_framework
            )
        )
コード例 #24
0
class TestJavaMaven(TestCase):
    SINGLE_BUILD_TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "testdata", "single-build")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()
        self.builder = LambdaBuilder(language='java', dependency_manager='maven', application_framework=None)
        self.runtime = 'java8'

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_build_single_build_with_deps_resources_exclude_test_jars(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, 'with-deps')
        manifest_path = os.path.join(source_dir, 'pom.xml')
        self.builder.build(source_dir, self.artifacts_dir, self.scratch_dir, manifest_path, runtime=self.runtime)
        expected_files = [p('aws', 'lambdabuilders', 'Main.class'), p('some_data.txt'),
                          p('lib', 'annotations-2.1.0.jar')]
        self.assert_artifact_contains_files(expected_files)
        self.assert_artifact_not_contains_file(p('lib', 'junit-4.12.jar'))
        self.assert_src_dir_not_touched(source_dir)

    def test_build_single_build_no_deps(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, 'no-deps')
        manifest_path = os.path.join(source_dir, 'pom.xml')
        self.builder.build(source_dir, self.artifacts_dir, self.scratch_dir, manifest_path, runtime=self.runtime)
        expected_files = [p('aws', 'lambdabuilders', 'Main.class'), p('some_data.txt')]
        self.assert_artifact_contains_files(expected_files)
        self.assert_artifact_not_contains_file(p('lib'))
        self.assert_src_dir_not_touched(source_dir)

    def test_build_single_build_with_deps_broken(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, 'with-deps-broken')
        manifest_path = os.path.join(source_dir, 'pom.xml')
        with self.assertRaises(WorkflowFailedError) as raised:
            self.builder.build(source_dir, self.artifacts_dir, self.scratch_dir, manifest_path, runtime=self.runtime)
        self.assertTrue(raised.exception.args[0].startswith('JavaMavenWorkflow:MavenBuild - Maven Failed'))
        self.assert_src_dir_not_touched(source_dir)

    def assert_artifact_contains_files(self, files):
        for f in files:
            self.assert_artifact_contains_file(f)

    def assert_artifact_contains_file(self, p):
        self.assertTrue(os.path.exists(os.path.join(self.artifacts_dir, p)))

    def assert_artifact_not_contains_file(self, p):
        self.assertFalse(os.path.exists(os.path.join(self.artifacts_dir, p)))

    def assert_src_dir_not_touched(self, source_dir):
        self.assertFalse(os.path.exists(os.path.join(source_dir, 'target')))
コード例 #25
0
class TestJavaGradle(TestCase):
    SINGLE_BUILD_TEST_DATA_DIR = os.path.join(os.path.dirname(__file__),
                                              "testdata", "single-build")
    MULTI_BUILD_TEST_DATA_DIR = os.path.join(os.path.dirname(__file__),
                                             "testdata", "multi-build")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()
        self.builder = LambdaBuilder(language='java',
                                     dependency_manager='gradle',
                                     application_framework=None)
        self.runtime = 'java11'

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_build_single_build_with_deps(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR, 'with-deps')
        manifest_path = os.path.join(source_dir, 'build.gradle')
        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime)
        expected_files = [
            p('aws', 'lambdabuilders', 'Main.class'),
            p('lib', 'annotations-2.1.0.jar')
        ]

        self.assert_artifact_contains_files(expected_files)

    def test_build_single_build_with_resources(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR,
                                  'with-resources')
        manifest_path = os.path.join(source_dir, 'build.gradle')
        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime)
        expected_files = [
            p('aws', 'lambdabuilders', 'Main.class'),
            p('some_data.txt'),
            p('lib', 'annotations-2.1.0.jar')
        ]

        self.assert_artifact_contains_files(expected_files)

    def test_build_single_build_with_test_deps_test_jars_not_included(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR,
                                  'with-test-deps')
        manifest_path = os.path.join(source_dir, 'build.gradle')
        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime)
        expected_files = [
            p('aws', 'lambdabuilders', 'Main.class'),
            p('lib', 'annotations-2.1.0.jar')
        ]

        self.assert_artifact_contains_files(expected_files)
        self.assert_artifact_not_contains_file(p('lib', 's3-2.1.0.jar'))

    def test_build_single_build_with_deps_gradlew(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR,
                                  'with-deps-gradlew')
        manifest_path = os.path.join(source_dir, 'build.gradle')
        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime,
                           executable_search_paths=[source_dir])
        expected_files = [
            p('aws', 'lambdabuilders', 'Main.class'),
            p('lib', 'annotations-2.1.0.jar')
        ]

        self.assert_artifact_contains_files(expected_files)

    def test_build_multi_build_with_deps_lambda1(self):
        parent_dir = os.path.join(self.MULTI_BUILD_TEST_DATA_DIR, 'with-deps')
        manifest_path = os.path.join(parent_dir, 'lambda1', 'build.gradle')

        lambda1_source = os.path.join(parent_dir, 'lambda1')
        self.builder.build(lambda1_source,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime)

        lambda1_expected_files = [
            p('aws', 'lambdabuilders', 'Lambda1_Main.class'),
            p('lib', 'annotations-2.1.0.jar')
        ]
        self.assert_artifact_contains_files(lambda1_expected_files)

    def test_build_multi_build_with_deps_lambda2(self):
        parent_dir = os.path.join(self.MULTI_BUILD_TEST_DATA_DIR, 'with-deps')
        manifest_path = os.path.join(parent_dir, 'lambda2', 'build.gradle')

        lambda2_source = os.path.join(parent_dir, 'lambda2')
        self.builder.build(lambda2_source,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime)

        lambda2_expected_files = [
            p('aws', 'lambdabuilders', 'Lambda2_Main.class'),
            p('lib', 'annotations-2.1.0.jar')
        ]
        self.assert_artifact_contains_files(lambda2_expected_files)

    def test_build_multi_build_with_deps_inter_module(self):
        parent_dir = os.path.join(self.MULTI_BUILD_TEST_DATA_DIR,
                                  'with-deps-inter-module')
        manifest_path = os.path.join(parent_dir, 'lambda1', 'build.gradle')

        lambda1_source = os.path.join(parent_dir, 'lambda1')
        self.builder.build(lambda1_source,
                           self.artifacts_dir,
                           self.scratch_dir,
                           manifest_path,
                           runtime=self.runtime)

        lambda1_expected_files = [
            p('aws', 'lambdabuilders', 'Lambda1_Main.class'),
            p('lib', 'annotations-2.1.0.jar'),
            p('lib', 'common.jar')
        ]
        self.assert_artifact_contains_files(lambda1_expected_files)

    def test_build_single_build_with_deps_broken(self):
        source_dir = os.path.join(self.SINGLE_BUILD_TEST_DATA_DIR,
                                  'with-deps-broken')
        manifest_path = os.path.join(source_dir, 'build.gradle')
        with self.assertRaises(WorkflowFailedError) as raised:
            self.builder.build(source_dir,
                               self.artifacts_dir,
                               self.scratch_dir,
                               manifest_path,
                               runtime=self.runtime)
        self.assertTrue(raised.exception.args[0].startswith(
            'JavaGradleWorkflow:GradleBuild - Gradle Failed'))

    def assert_artifact_contains_files(self, files):
        for f in files:
            self.assert_artifact_contains_file(f)

    def assert_artifact_contains_file(self, p):
        self.assertTrue(os.path.exists(os.path.join(self.artifacts_dir, p)))

    def assert_artifact_not_contains_file(self, p):
        self.assertFalse(os.path.exists(os.path.join(self.artifacts_dir, p)))

    def assert_zip_contains(self, zip_path, files):
        with ZipFile(zip_path) as z:
            zip_names = set(z.namelist())
            self.assertTrue(set(files).issubset(zip_names))
コード例 #26
0
class TestGoDep(TestCase):
    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "data")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        os.environ["GOPATH"] = self.TEST_DATA_FOLDER

        self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "src", "nodeps")

        self.builder = LambdaBuilder(language="go", dependency_manager="dep", application_framework=None)

        self.runtime = "go1.x"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_builds_project_with_no_deps(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "src", "nodeps")

        self.builder.build(
            source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            os.path.join(source_dir, "Gopkg.toml"),
            runtime=self.runtime,
            options={"artifact_executable_name": "main"},
        )

        expected_files = {"main"}
        output_files = set(os.listdir(self.artifacts_dir))

        self.assertEqual(expected_files, output_files)

    def test_builds_project_and_excludes_hidden_aws_sam(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "src", "excluded-files")

        self.builder.build(
            source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            os.path.join(source_dir, "Gopkg.toml"),
            runtime=self.runtime,
            options={"artifact_executable_name": "main"},
        )

        expected_files = {"main"}
        output_files = set(os.listdir(self.artifacts_dir))

        self.assertEqual(expected_files, output_files)

    def test_builds_project_with_no_gopkg_file(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "src", "no-gopkg")

        with self.assertRaises(WorkflowFailedError) as ex:
            self.builder.build(
                source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                os.path.join(source_dir, "Gopkg.toml"),
                runtime=self.runtime,
                options={"artifact_executable_name": "main"},
            )

        self.assertEqual(
            "GoDepBuilder:DepEnsure - Exec Failed: could not find project Gopkg.toml,"
            + " use dep init to initiate a manifest",
            str(ex.exception),
        )

    def test_builds_project_with_remote_deps(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "src", "remote-deps")

        self.builder.build(
            source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            os.path.join(source_dir, "Gopkg.toml"),
            runtime=self.runtime,
            options={"artifact_executable_name": "main"},
        )

        expected_files = {"main"}
        output_files = set(os.listdir(self.artifacts_dir))

        self.assertEqual(expected_files, output_files)

    def test_builds_project_with_failed_remote_deps(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "src", "failed-remote")

        with self.assertRaises(WorkflowFailedError) as ex:
            self.builder.build(
                source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                os.path.join(source_dir, "Gopkg.toml"),
                runtime=self.runtime,
                options={"artifact_executable_name": "main"},
            )

        # The full message is super long, so part of it is fine.
        self.assertNotEqual(str(ex.exception).find("unable to deduce repository and source type for"), -1)
コード例 #27
0
class TestCustomMakeWorkflow(TestCase):
    """
    Verifies that `custom_make` workflow works by building a Lambda that requires Numpy
    """

    MAKEFILE_DIRECTORY = "makefile-root"
    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata",
                                    MAKEFILE_DIRECTORY)

    def setUp(self):
        self.source_dir = self.TEST_DATA_FOLDER
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.manifest_path_valid = os.path.join(self.TEST_DATA_FOLDER,
                                                "Makefile")

        self.test_data_files = {
            "__init__.py", "main.py", "requirements-requests.txt"
        }

        self.builder = LambdaBuilder(language="provided",
                                     dependency_manager=None,
                                     application_framework=None)
        self.runtime = "provided"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_must_build_python_project_through_makefile(self):
        self.builder.build(
            self.source_dir,
            self.artifacts_dir,
            self.scratch_dir,
            self.manifest_path_valid,
            runtime=self.runtime,
            options={"build_logical_id": "HelloWorldFunction"},
        )
        dependencies_installed = {
            "chardet",
            "urllib3",
            "idna",
            "urllib3-1.25.9.dist-info",
            "chardet-3.0.4.dist-info",
            "certifi-2020.4.5.2.dist-info",
            "certifi",
            "idna-2.10.dist-info",
            "requests",
            "requests-2.23.0.dist-info",
        }

        expected_files = self.test_data_files.union(dependencies_installed)
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEquals(expected_files, output_files)

    def test_must_build_python_project_through_makefile_unknown_target(self):
        with self.assertRaises(WorkflowFailedError):
            self.builder.build(
                self.source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                self.manifest_path_valid,
                runtime=self.runtime,
                options={"build_logical_id": "HelloWorldFunction2"},
            )
コード例 #28
0
class TestPythonPipWorkflow(TestCase):
    """
    Verifies that `python_pip` workflow works by building a Lambda that requires Numpy
    """

    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata")

    def setUp(self):
        self.source_dir = self.TEST_DATA_FOLDER
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.manifest_path_valid = os.path.join(self.TEST_DATA_FOLDER,
                                                "requirements-numpy.txt")
        self.manifest_path_invalid = os.path.join(self.TEST_DATA_FOLDER,
                                                  "requirements-invalid.txt")

        self.test_data_files = {
            "__init__.py", "main.py", "requirements-invalid.txt",
            "requirements-numpy.txt"
        }

        self.builder = LambdaBuilder(language="python",
                                     dependency_manager="pip",
                                     application_framework=None)
        self.runtime = "{language}{major}.{minor}".format(
            language=self.builder.capability.language,
            major=sys.version_info.major,
            minor=sys.version_info.minor)
        self.runtime_mismatch = {
            "python3.6": "python2.7",
            "python3.7": "python2.7",
            "python2.7": "python3.8",
            "python3.8": "python2.7",
        }

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_must_build_python_project(self):
        self.builder.build(self.source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           self.manifest_path_valid,
                           runtime=self.runtime)

        if self.runtime == "python2.7":
            expected_files = self.test_data_files.union(
                {"numpy", "numpy-1.15.4.data", "numpy-1.15.4.dist-info"})
        elif self.runtime == "python3.6":
            expected_files = self.test_data_files.union(
                {"numpy", "numpy-1.17.4.dist-info"})
        else:
            expected_files = self.test_data_files.union(
                {"numpy", "numpy-1.20.3.dist-info", "numpy.libs"})
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEqual(expected_files, output_files)

    def test_mismatch_runtime_python_project(self):
        # NOTE : Build still works if other versions of python are accessible on the path. eg: /usr/bin/python2.7
        # is still accessible within a python 3 virtualenv.
        try:
            self.builder.build(
                self.source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                self.manifest_path_valid,
                runtime=self.runtime_mismatch[self.runtime],
            )
        except WorkflowFailedError as ex:
            self.assertIn("Binary validation failed", str(ex))

    def test_runtime_validate_python_project_fail_open_unsupported_runtime(
            self):
        with self.assertRaises(WorkflowFailedError):
            self.builder.build(self.source_dir,
                               self.artifacts_dir,
                               self.scratch_dir,
                               self.manifest_path_valid,
                               runtime="python2.8")

    def test_must_fail_to_resolve_dependencies(self):

        with self.assertRaises(WorkflowFailedError) as ctx:
            self.builder.build(self.source_dir,
                               self.artifacts_dir,
                               self.scratch_dir,
                               self.manifest_path_invalid,
                               runtime=self.runtime)

        # In Python2 a 'u' is now added to the exception string. To account for this, we see if either one is in the
        # output
        message_in_exception = "Invalid requirement: 'adfasf=1.2.3'" in str(
            ctx.exception) or "Invalid requirement: u'adfasf=1.2.3'" in str(
                ctx.exception)
        self.assertTrue(message_in_exception)

    def test_must_fail_if_requirements_not_found(self):

        with self.assertRaises(WorkflowFailedError) as ctx:
            self.builder.build(
                self.source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                os.path.join("non", "existent", "manifest"),
                runtime=self.runtime,
            )

            self.builder.build(
                self.source_dir,
                self.artifacts_dir,
                self.scratch_dir,
                os.path.join("non", "existent", "manifest"),
                runtime=self.runtime,
            )

        self.assertIn("Requirements file not found", str(ctx.exception))
コード例 #29
0
ファイル: __main__.py プロジェクト: aws/aws-lambda-builders
def main():  # pylint: disable=too-many-statements
    """
    Implementation of CLI Interface. Handles only one JSON-RPC method at a time and responds with data

    Input is passed as JSON string either through stdin or as the first argument to the command. Output is always
    printed to stdout.
    """

    # For now the request is not validated
    if len(sys.argv) > 1:
        request_str = sys.argv[1]
        LOG.debug("Using the request object from command line argument")
    else:
        LOG.debug("Reading the request object from stdin")
        request_str = sys.stdin.read()

    request = json.loads(request_str)
    request_id = request["id"]
    params = request["params"]

    # Currently, this is the only supported method
    if request["method"] != "LambdaBuilder.build":
        response = _error_response(request_id, -32601, "Method unavailable")
        return _write_response(response, 1)

    try:
        protocol_version = _parse_version(params.get("__protocol_version"))
        version_compatibility_check(protocol_version)

    except ValueError:
        response = _error_response(request_id, 505, "Unsupported Protocol Version")
        return _write_response(response, 1)

    capabilities = params["capability"]
    supported_workflows = params.get("supported_workflows")

    exit_code = 0
    response = None

    try:
        builder = LambdaBuilder(
            language=capabilities["language"],
            dependency_manager=capabilities["dependency_manager"],
            application_framework=capabilities["application_framework"],
            supported_workflows=supported_workflows,
        )

        artifacts_dir = params["artifacts_dir"]
        builder.build(
            params["source_dir"],
            params["artifacts_dir"],
            params["scratch_dir"],
            params["manifest_path"],
            executable_search_paths=params.get("executable_search_paths", None),
            runtime=params["runtime"],
            optimizations=params["optimizations"],
            options=params["options"],
            mode=params.get("mode", None),
            download_dependencies=params.get("download_dependencies", True),
            dependencies_dir=params.get("dependencies_dir", None),
            combine_dependencies=params.get("combine_dependencies", True),
            architecture=params.get("architecture", X86_64),
            is_building_layer=params.get("is_building_layer", False),
            experimental_flags=params.get("experimental_flags", []),
        )

        # Return a success response
        response = _success_response(request_id, artifacts_dir)

    except (WorkflowNotFoundError, WorkflowUnknownError, WorkflowFailedError) as ex:
        LOG.debug("Builder workflow failed", exc_info=ex)
        exit_code = 1
        response = _error_response(request_id, 400, str(ex))

    except Exception as ex:
        LOG.debug("Builder crashed", exc_info=ex)
        exit_code = 1
        response = _error_response(request_id, 500, str(ex))

    _write_response(response, exit_code)
コード例 #30
0
class TestNodejsNpmWorkflow(TestCase):
    """
    Verifies that `nodejs_npm` workflow works by building a Lambda using NPM
    """

    TEST_DATA_FOLDER = os.path.join(os.path.dirname(__file__), "testdata")

    def setUp(self):
        self.artifacts_dir = tempfile.mkdtemp()
        self.scratch_dir = tempfile.mkdtemp()

        self.no_deps = os.path.join(self.TEST_DATA_FOLDER, "no-deps")

        self.builder = LambdaBuilder(language="nodejs",
                                     dependency_manager="npm",
                                     application_framework=None)
        self.runtime = "nodejs8.10"

    def tearDown(self):
        shutil.rmtree(self.artifacts_dir)
        shutil.rmtree(self.scratch_dir)

    def test_builds_project_without_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "no-deps")

        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           os.path.join(source_dir, "package.json"),
                           runtime=self.runtime)

        expected_files = {"package.json", "included.js"}
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEquals(expected_files, output_files)

    def test_builds_project_with_remote_dependencies(self):
        source_dir = os.path.join(self.TEST_DATA_FOLDER, "npm-deps")

        self.builder.build(source_dir,
                           self.artifacts_dir,
                           self.scratch_dir,
                           os.path.join(source_dir, "package.json"),
                           runtime=self.runtime)

        expected_files = {"package.json", "included.js", "node_modules"}
        output_files = set(os.listdir(self.artifacts_dir))
        self.assertEquals(expected_files, output_files)

        expected_modules = {"minimal-request-promise"}
        output_modules = set(
            os.listdir(os.path.join(self.artifacts_dir, "node_modules")))
        self.assertEquals(expected_modules, output_modules)

    def test_fails_if_npm_cannot_resolve_dependencies(self):

        source_dir = os.path.join(self.TEST_DATA_FOLDER, "broken-deps")

        with self.assertRaises(WorkflowFailedError) as ctx:
            self.builder.build(source_dir,
                               self.artifacts_dir,
                               self.scratch_dir,
                               os.path.join(source_dir, "package.json"),
                               runtime=self.runtime)

        self.assertIn(
            "No matching version found for [email protected]_EXISTENT",
            str(ctx.exception))

    def test_fails_if_package_json_is_broken(self):

        source_dir = os.path.join(self.TEST_DATA_FOLDER, "broken-package")

        with self.assertRaises(WorkflowFailedError) as ctx:
            self.builder.build(source_dir,
                               self.artifacts_dir,
                               self.scratch_dir,
                               os.path.join(source_dir, "package.json"),
                               runtime=self.runtime)

        self.assertIn("Unexpected end of JSON input", str(ctx.exception))