def test_must_return_function_value(self):
        provider = SamFunctionProvider({})
        provider.functions = {
            "func1": "value"
        }  # Cheat a bit here by setting the value of this property directly

        self.assertEqual("value", provider.get("func1"))
示例#2
0
    def test_must_return_function_value(self):
        provider = SamFunctionProvider([])
        # Cheat a bit here by setting the value of this property directly
        function = Function(
            name="not-value",
            functionname="value",
            runtime=None,
            handler=None,
            codeuri=None,
            memory=None,
            timeout=None,
            environment=None,
            rolearn=None,
            layers=[],
            events=None,
            metadata=None,
            inlinecode=None,
            imageuri=None,
            imageconfig=None,
            packagetype=None,
            codesign_config_arn=None,
            stack_path=STACK_PATH,
        )
        provider.functions = {"func1": function}

        self.assertEqual(function, provider.get("value"))
示例#3
0
    def test_must_return_function_value(self):
        provider = SamFunctionProvider({})
        # Cheat a bit here by setting the value of this property directly
        function = Function(
            name="not-value",
            functionname="value",
            runtime=None,
            handler=None,
            codeuri=None,
            memory=None,
            timeout=None,
            environment=None,
            rolearn=None,
            layers=[],
        )
        provider.functions = {"func1": function}

        self.assertEqual(function, provider.get("value"))
示例#4
0
class BuildContext:
    # Build directories need not be world writable.
    # This is usually a optimal permission for directories
    _BUILD_DIR_PERMISSIONS = 0o755

    def __init__(
        self,
        resource_identifier,
        template_file,
        base_dir,
        build_dir,
        mode,
        manifest_path=None,
        clean=False,
        use_container=False,
        parameter_overrides=None,
        docker_network=None,
        skip_pull_image=False,
    ):

        self._resource_identifier = resource_identifier
        self._template_file = template_file
        self._base_dir = base_dir
        self._build_dir = build_dir
        self._manifest_path = manifest_path
        self._clean = clean
        self._use_container = use_container
        self._parameter_overrides = parameter_overrides
        self._docker_network = docker_network
        self._skip_pull_image = skip_pull_image
        self._mode = mode

        self._function_provider = None
        self._layer_provider = None
        self._template_dict = None
        self._app_builder = None
        self._container_manager = None

    def __enter__(self):
        self._template_dict = get_template_data(self._template_file)

        self._function_provider = SamFunctionProvider(
            self._template_dict, self._parameter_overrides)
        self._layer_provider = SamLayerProvider(self._template_dict,
                                                self._parameter_overrides)

        if not self._base_dir:
            # Base directory, if not provided, is the directory containing the template
            self._base_dir = str(
                pathlib.Path(self._template_file).resolve().parent)

        self._build_dir = self._setup_build_dir(self._build_dir, self._clean)

        if self._use_container:
            self._container_manager = ContainerManager(
                docker_network_id=self._docker_network,
                skip_pull_image=self._skip_pull_image)

        return self

    def __exit__(self, *args):
        pass

    @staticmethod
    def _setup_build_dir(build_dir, clean):
        build_path = pathlib.Path(build_dir)

        if os.path.abspath(str(build_path)) == os.path.abspath(
                str(pathlib.Path.cwd())):
            exception_message = "Failing build: Running a build with build-dir as current working directory is extremely dangerous since the build-dir contents is first removed. This is no longer supported, please remove the '--build-dir' option from the command to allow the build artifacts to be placed in the directory your template is in."
            raise InvalidBuildDirException(exception_message)

        if build_path.exists() and os.listdir(build_dir) and clean:
            # build folder contains something inside. Clear everything.
            shutil.rmtree(build_dir)

        build_path.mkdir(mode=BuildContext._BUILD_DIR_PERMISSIONS,
                         parents=True,
                         exist_ok=True)

        # ensure path resolving is done after creation: https://bugs.python.org/issue32434
        return str(build_path.resolve())

    @property
    def container_manager(self):
        return self._container_manager

    @property
    def function_provider(self):
        return self._function_provider

    @property
    def layer_provider(self):
        return self._layer_provider

    @property
    def template_dict(self):
        return self._template_dict

    @property
    def build_dir(self):
        return self._build_dir

    @property
    def base_dir(self):
        return self._base_dir

    @property
    def use_container(self):
        return self._use_container

    @property
    def output_template_path(self):
        return os.path.join(self._build_dir, "template.yaml")

    @property
    def original_template_path(self):
        return os.path.abspath(self._template_file)

    @property
    def manifest_path_override(self):
        if self._manifest_path:
            return os.path.abspath(self._manifest_path)

        return None

    @property
    def mode(self):
        return self._mode

    @property
    def resources_to_build(self):
        """
        Function return resources that should be build by current build command. This function considers
        Lambda Functions and Layers with build method as buildable resources.
        Returns
        -------
        ResourcesToBuildCollector
        """
        result = ResourcesToBuildCollector()
        if self._resource_identifier:
            self._collect_single_function_and_dependent_layers(
                self._resource_identifier, result)
            self._collect_single_buildable_layer(self._resource_identifier,
                                                 result)

            if not result.functions and not result.layers:
                all_resources = [
                    f.name for f in self._function_provider.get_all()
                ]
                all_resources.extend(
                    [l.name for l in self._layer_provider.get_all()])

                available_resource_message = f"{self._resource_identifier} not found. Possible options in your " \
                                             f"template: {all_resources}"
                LOG.info(available_resource_message)
                raise ResourceNotFound(
                    f"Unable to find a function or layer with name '{self._resource_identifier}'"
                )
            return result
        result.add_functions(self._function_provider.get_all())
        result.add_layers([
            l for l in self._layer_provider.get_all()
            if l.build_method is not None
        ])
        return result

    @property
    def is_building_specific_resource(self):
        """
        Whether customer requested to build a specific resource alone in isolation,
        by specifying function_identifier to the build command.
        Ex: sam build MyServerlessFunction
        :return: True if user requested to build specific resource, False otherwise
        """
        return bool(self._resource_identifier)

    def _collect_single_function_and_dependent_layers(self,
                                                      resource_identifier,
                                                      resource_collector):
        """
        Populate resource_collector with function with provided identifier and all layers that function need to be
        build in resource_collector
        Parameters
        ----------
        resource_collector: Collector that will be populated with resources.

        Returns
        -------
        ResourcesToBuildCollector

        """
        function = self._function_provider.get(resource_identifier)
        if not function:
            # No function found
            return

        resource_collector.add_function(function)
        resource_collector.add_layers(
            [l for l in function.layers if l.build_method is not None])

    def _collect_single_buildable_layer(self, resource_identifier,
                                        resource_collector):
        """
        Populate resource_collector with layer with provided identifier.

        Parameters
        ----------
        resource_collector

        Returns
        -------

        """
        layer = self._layer_provider.get(resource_identifier)
        if not layer:
            # No layer found
            return
        if layer and layer.build_method is None:
            LOG.error("Layer %s is missing BuildMethod Metadata.",
                      self._function_provider)
            raise MissingBuildMethodException(
                f"Build method missing in layer {resource_identifier}.")

        resource_collector.add_layer(layer)
示例#5
0
    def test_return_none_if_function_not_found(self):
        provider = SamFunctionProvider({})

        self.assertIsNone(provider.get("somefunc"),
                          "Must return None when Function is not found")
示例#6
0
    def test_raise_on_invalid_name(self):
        provider = SamFunctionProvider({})

        with self.assertRaises(ValueError):
            provider.get(None)
示例#7
0
class TestSamFunctionProviderEndToEnd(TestCase):
    """
    Test all public methods with an input template
    """

    TEMPLATE = {
        "Resources": {
            "SamFunctions": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "FunctionName": "SamFunc1",
                    "CodeUri": "/usr/foo/bar",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFunc2": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    # CodeUri is unsupported S3 location
                    "CodeUri": "s3://bucket/key",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFunc3": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    # CodeUri is unsupported S3 location
                    "CodeUri": {
                        "Bucket": "bucket",
                        "Key": "key"
                    },
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFuncWithFunctionNameOverride": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "FunctionName": "SamFuncWithFunctionNameOverride-x",
                    "CodeUri": "/usr/foo/bar",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFunc1": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Code": {
                        "S3Bucket": "bucket",
                        "S3Key": "key"
                    },
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFuncWithLocalPath": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Code": "./some/path/to/code",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler"
                },
            },
            "LambdaFuncWithFunctionNameOverride": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "FunctionName": "LambdaFuncWithFunctionNameOverride-x",
                    "Code": "./some/path/to/code",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFuncWithCodeSignConfig": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "FunctionName": "LambdaFuncWithCodeSignConfig",
                    "Code": "./some/path/to/code",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                    "CodeSigningConfigArn": "codeSignConfigArn",
                },
            },
            "OtherResource": {
                "Type": "AWS::Serverless::Api",
                "Properties": {
                    "StageName": "prod",
                    "DefinitionUri": "s3://bucket/key"
                },
            },
        }
    }

    def setUp(self):
        self.parameter_overrides = {}
        self.provider = SamFunctionProvider(
            self.TEMPLATE, parameter_overrides=self.parameter_overrides)

    @parameterized.expand([
        (
            "SamFunc1",
            Function(
                name="SamFunctions",
                functionname="SamFunc1",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "SamFunctions",
            Function(
                name="SamFunctions",
                functionname="SamFunc1",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "SamFunc2",
            Function(
                name="SamFunc2",
                functionname="SamFunc2",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "SamFunc3",
            Function(
                name="SamFunc3",
                functionname="SamFunc3",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "SamFuncWithFunctionNameOverride-x",
            Function(
                name="SamFuncWithFunctionNameOverride",
                functionname="SamFuncWithFunctionNameOverride-x",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "LambdaFunc1",
            Function(
                name="LambdaFunc1",
                functionname="LambdaFunc1",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "LambdaFuncWithLocalPath",
            Function(
                name="LambdaFuncWithLocalPath",
                functionname="LambdaFuncWithLocalPath",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="./some/path/to/code",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "LambdaFuncWithFunctionNameOverride-x",
            Function(
                name="LambdaFuncWithFunctionNameOverride",
                functionname="LambdaFuncWithFunctionNameOverride-x",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="./some/path/to/code",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn=None,
            ),
        ),
        (
            "LambdaFuncWithCodeSignConfig",
            Function(
                name="LambdaFuncWithCodeSignConfig",
                functionname="LambdaFuncWithCodeSignConfig",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="./some/path/to/code",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                codesign_config_arn="codeSignConfigArn",
            ),
        ),
    ])
    def test_get_must_return_each_function(self, name, expected_output):

        actual = self.provider.get(name)
        self.assertEqual(actual, expected_output)

    def test_get_all_must_return_all_functions(self):

        result = {f.name for f in self.provider.get_all()}
        expected = {
            "SamFunctions",
            "SamFunc2",
            "SamFunc3",
            "SamFuncWithFunctionNameOverride",
            "LambdaFunc1",
            "LambdaFuncWithLocalPath",
            "LambdaFuncWithFunctionNameOverride",
            "LambdaFuncWithCodeSignConfig",
        }

        self.assertEqual(result, expected)
示例#8
0
class BuildContext:

    # Build directories need not be world writable.
    # This is usually a optimal permission for directories
    _BUILD_DIR_PERMISSIONS = 0o755

    def __init__(
        self,
        function_identifier,
        template_file,
        base_dir,
        build_dir,
        mode,
        manifest_path=None,
        clean=False,
        use_container=False,
        parameter_overrides=None,
        docker_network=None,
        skip_pull_image=False,
    ):

        self._function_identifier = function_identifier
        self._template_file = template_file
        self._base_dir = base_dir
        self._build_dir = build_dir
        self._manifest_path = manifest_path
        self._clean = clean
        self._use_container = use_container
        self._parameter_overrides = parameter_overrides
        self._docker_network = docker_network
        self._skip_pull_image = skip_pull_image
        self._mode = mode

        self._function_provider = None
        self._template_dict = None
        self._app_builder = None
        self._container_manager = None

    def __enter__(self):
        self._template_dict = get_template_data(self._template_file)

        self._function_provider = SamFunctionProvider(
            self._template_dict, self._parameter_overrides)

        if not self._base_dir:
            # Base directory, if not provided, is the directory containing the template
            self._base_dir = str(
                pathlib.Path(self._template_file).resolve().parent)

        self._build_dir = self._setup_build_dir(self._build_dir, self._clean)

        if self._use_container:
            self._container_manager = ContainerManager(
                docker_network_id=self._docker_network,
                skip_pull_image=self._skip_pull_image)

        return self

    def __exit__(self, *args):
        pass

    @staticmethod
    def _setup_build_dir(build_dir, clean):
        build_path = pathlib.Path(build_dir)

        if os.path.abspath(str(build_path)) == os.path.abspath(
                str(pathlib.Path.cwd())):
            exception_message = "Failing build: Running a build with build-dir as current working directory is extremely dangerous since the build-dir contents is first removed. This is no longer supported, please remove the '--build-dir' option from the command to allow the build artifacts to be placed in the directory your template is in."
            raise InvalidBuildDirException(exception_message)

        if build_path.exists() and os.listdir(build_dir) and clean:
            # build folder contains something inside. Clear everything.
            shutil.rmtree(build_dir)

        build_path.mkdir(mode=BuildContext._BUILD_DIR_PERMISSIONS,
                         parents=True,
                         exist_ok=True)

        # ensure path resolving is done after creation: https://bugs.python.org/issue32434
        return str(build_path.resolve())

    @property
    def container_manager(self):
        return self._container_manager

    @property
    def function_provider(self):
        return self._function_provider

    @property
    def template_dict(self):
        return self._template_dict

    @property
    def build_dir(self):
        return self._build_dir

    @property
    def base_dir(self):
        return self._base_dir

    @property
    def use_container(self):
        return self._use_container

    @property
    def output_template_path(self):
        return os.path.join(self._build_dir, "template.yaml")

    @property
    def original_template_path(self):
        return os.path.abspath(self._template_file)

    @property
    def manifest_path_override(self):
        if self._manifest_path:
            return os.path.abspath(self._manifest_path)

        return None

    @property
    def mode(self):
        return self._mode

    @property
    def functions_to_build(self):
        if self._function_identifier:
            function = self._function_provider.get(self._function_identifier)

            if not function:
                all_functions = [
                    f.name for f in self._function_provider.get_all()
                ]
                available_function_message = "{} not found. Possible options in your template: {}".format(
                    self._function_identifier, all_functions)
                LOG.info(available_function_message)
                raise FunctionNotFound(
                    "Unable to find a Function with name '{}'".format(
                        self._function_identifier))

            return [function]

        return self._function_provider.get_all()
示例#9
0
class TestSamFunctionProviderEndToEnd(TestCase):
    """
    Test all public methods with an input template and its child templates
    """

    TEMPLATE = {
        "Resources": {
            "SamFunctions": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "FunctionName": "SamFunc1",
                    "CodeUri": "/usr/foo/bar",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFuncWithInlineCode": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "FunctionName": "SamFuncWithInlineCode",
                    "InlineCode": "testcode",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFunc2": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    # CodeUri is unsupported S3 location
                    "CodeUri": "s3://bucket/key",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFunc3": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    # CodeUri is unsupported S3 location
                    "CodeUri": {
                        "Bucket": "bucket",
                        "Key": "key"
                    },
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "SamFunc4": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "ImageUri":
                    "123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo",
                    "PackageType": IMAGE
                },
            },
            "SamFuncWithFunctionNameOverride": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "FunctionName": "SamFuncWithFunctionNameOverride-x",
                    "CodeUri": "/usr/foo/bar",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFunc1": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Code": {
                        "S3Bucket": "bucket",
                        "S3Key": "key"
                    },
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFuncWithInlineCode": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Code": {
                        "ZipFile": "testcode"
                    },
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFunc2": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Code": {
                        "ImageUri":
                        "123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo"
                    },
                    "PackageType": IMAGE,
                },
            },
            "LambdaFuncWithLocalPath": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "Code": "./some/path/to/code",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler"
                },
            },
            "LambdaFuncWithFunctionNameOverride": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "FunctionName": "LambdaFuncWithFunctionNameOverride-x",
                    "Code": "./some/path/to/code",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
            "LambdaFuncWithCodeSignConfig": {
                "Type": "AWS::Lambda::Function",
                "Properties": {
                    "FunctionName": "LambdaFuncWithCodeSignConfig",
                    "Code": "./some/path/to/code",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                    "CodeSigningConfigArn": "codeSignConfigArn",
                },
            },
            "OtherResource": {
                "Type": "AWS::Serverless::Api",
                "Properties": {
                    "StageName": "prod",
                    "DefinitionUri": "s3://bucket/key"
                },
            },
            "ChildStack": {
                "Type": "AWS::Serverless::Application",
                "Properties": {
                    "Location": "./child.yaml"
                },
            },
        }
    }

    CHILD_TEMPLATE = {
        "Resources": {
            "SamFunctionsInChild": {
                "Type": "AWS::Serverless::Function",
                "Properties": {
                    "FunctionName": "SamFunctionsInChildName",
                    "CodeUri": "/usr/foo/bar",
                    "Runtime": "nodejs4.3",
                    "Handler": "index.handler",
                },
            },
        }
    }

    def setUp(self):
        self.parameter_overrides = {}
        root_stack = Stack("", "", "template.yaml", self.parameter_overrides,
                           self.TEMPLATE)
        child_stack = Stack("", "ChildStack", "./child.yaml", None,
                            self.CHILD_TEMPLATE)
        with patch("samcli.lib.providers.sam_stack_provider.get_template_data"
                   ) as get_template_data_mock:
            get_template_data_mock.side_effect = lambda t: {
                "template.yaml": self.TEMPLATE,
                "./child.yaml": self.CHILD_TEMPLATE,
            }
            self.provider = SamFunctionProvider([root_stack, child_stack])

    @parameterized.expand([
        (
            "SamFunc1",
            Function(
                name="SamFunctions",
                functionname="SamFunc1",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "SamFuncWithInlineCode",
            Function(
                name="SamFuncWithInlineCode",
                functionname="SamFuncWithInlineCode",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=None,
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode="testcode",
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "SamFunctions",
            Function(
                name="SamFunctions",
                functionname="SamFunc1",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "SamFunc2",
            Function(
                name="SamFunc2",
                functionname="SamFunc2",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "SamFunc3",
            Function(
                name="SamFunc3",
                functionname="SamFunc3",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                metadata=None,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "SamFunc4",
            Function(
                name="SamFunc4",
                functionname="SamFunc4",
                runtime=None,
                handler=None,
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                inlinecode=None,
                imageuri="123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo",
                imageconfig=None,
                packagetype=IMAGE,
                metadata=None,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "SamFuncWithFunctionNameOverride-x",
            Function(
                name="SamFuncWithFunctionNameOverride",
                functionname="SamFuncWithFunctionNameOverride-x",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "LambdaFunc1",
            Function(
                name="LambdaFunc1",
                functionname="LambdaFunc1",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "LambdaFuncWithInlineCode",
            Function(
                name="LambdaFuncWithInlineCode",
                functionname="LambdaFuncWithInlineCode",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri=None,
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode="testcode",
                codesign_config_arn=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                stack_path="",
            ),
        ),
        (
            "LambdaFunc2",
            Function(
                name="LambdaFunc2",
                functionname="LambdaFunc2",
                runtime=None,
                handler=None,
                codeuri=".",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri="123456789012.dkr.ecr.us-east-1.amazonaws.com/myrepo",
                imageconfig=None,
                packagetype=IMAGE,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "LambdaFuncWithLocalPath",
            Function(
                name="LambdaFuncWithLocalPath",
                functionname="LambdaFuncWithLocalPath",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="./some/path/to/code",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                codesign_config_arn=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                stack_path="",
            ),
        ),
        (
            "LambdaFuncWithFunctionNameOverride-x",
            Function(
                name="LambdaFuncWithFunctionNameOverride",
                functionname="LambdaFuncWithFunctionNameOverride-x",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="./some/path/to/code",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="",
            ),
        ),
        (
            "LambdaFuncWithCodeSignConfig",
            Function(
                name="LambdaFuncWithCodeSignConfig",
                functionname="LambdaFuncWithCodeSignConfig",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="./some/path/to/code",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn="codeSignConfigArn",
                stack_path="",
            ),
        ),
        (
            posixpath.join("ChildStack", "SamFunctionsInChild"),
            Function(
                name="SamFunctionsInChild",
                functionname="SamFunctionsInChildName",
                runtime="nodejs4.3",
                handler="index.handler",
                codeuri="/usr/foo/bar",
                memory=None,
                timeout=None,
                environment=None,
                rolearn=None,
                layers=[],
                events=None,
                metadata=None,
                inlinecode=None,
                imageuri=None,
                imageconfig=None,
                packagetype=ZIP,
                codesign_config_arn=None,
                stack_path="ChildStack",
            ),
        ),
    ])
    def test_get_must_return_each_function(self, name, expected_output):

        actual = self.provider.get(name)
        self.assertEqual(actual, expected_output)

    def test_get_all_must_return_all_functions(self):

        result = {
            posixpath.join(f.stack_path, f.name)
            for f in self.provider.get_all()
        }
        expected = {
            "SamFunctions",
            "SamFuncWithInlineCode",
            "SamFunc2",
            "SamFunc3",
            "SamFunc4",
            "SamFuncWithFunctionNameOverride",
            "LambdaFunc1",
            "LambdaFuncWithInlineCode",
            "LambdaFunc2",
            "LambdaFuncWithLocalPath",
            "LambdaFuncWithFunctionNameOverride",
            "LambdaFuncWithCodeSignConfig",
            posixpath.join("ChildStack", "SamFunctionsInChild"),
        }

        self.assertEqual(result, expected)