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"))
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"))
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"))
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)
def test_return_none_if_function_not_found(self): provider = SamFunctionProvider({}) self.assertIsNone(provider.get("somefunc"), "Must return None when Function is not found")
def test_raise_on_invalid_name(self): provider = SamFunctionProvider({}) with self.assertRaises(ValueError): provider.get(None)
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)
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()
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)