From 7de9dbe22fbc0207addc237dd8b4404868bb789e Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 12:58:08 +0900 Subject: [PATCH 1/8] Greengrass Implement create_function_definition --- moto/greengrass/models.py | 86 +++++++++++++++++++ moto/greengrass/responses.py | 15 ++++ moto/greengrass/urls.py | 1 + .../test_greengrass_functions.py | 41 +++++++++ 4 files changed, 143 insertions(+) create mode 100644 tests/test_greengrass/test_greengrass_functions.py diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 787121619ea..77a05a27baf 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -167,6 +167,58 @@ def to_dict(self): } +class FakeFunctionDefinition(BaseModel): + def __init__(self, region_name, name, initial_version): + self.region_name = region_name + self.id = str(uuid.uuid4()) + self.arn = f"arn:aws:greengrass:{self.region_name}:{get_account_id()}:/greengrass/definition/functions/{self.id}" + self.created_at_datetime = datetime.utcnow() + self.update_at_datetime = datetime.utcnow() + self.latest_version = "" + self.latest_version_arn = "" + self.name = name + self.initial_version = initial_version + + def to_dict(self): + res = { + "Arn": self.arn, + "CreationTimestamp": iso_8601_datetime_with_milliseconds( + self.created_at_datetime + ), + "Id": self.id, + "LastUpdatedTimestamp": iso_8601_datetime_with_milliseconds( + self.update_at_datetime + ), + "LatestVersion": self.latest_version, + "LatestVersionArn": self.latest_version_arn, + } + if self.name is not None: + res["Name"] = self.name + return res + + +class FakeFunctionDefinitionVersion(BaseModel): + def __init__(self, region_name, function_definition_id, functions, default_config): + self.region_name = region_name + self.function_definition_id = function_definition_id + self.functions = functions + self.default_config = default_config + self.version = str(uuid.uuid4()) + self.arn = f"arn:aws:greengrass:{self.region_name}:{get_account_id()}:/greengrass/definition/functions/{self.function_definition_id}/versions/{self.version}" + self.created_at_datetime = datetime.utcnow() + + def to_dict(self): + return { + "Arn": self.arn, + "CreationTimestamp": iso_8601_datetime_with_milliseconds( + self.created_at_datetime + ), + "Definition": {"Functions": self.functions}, + "Id": self.function_definition_id, + "Version": self.version, + } + + class GreengrassBackend(BaseBackend): def __init__(self, region_name, account_id): super().__init__(region_name, account_id) @@ -410,5 +462,39 @@ def _validate_resources(resources): f", but got: {device_source_path}])", ) + def create_function_definition(self, name, initial_version): + func_def = FakeFunctionDefinition(self.region_name, name, initial_version) + self.function_definitions[func_def.id] = func_def + init_ver = func_def.initial_version + init_func_def = init_ver.get("Functions", {}) + init_config = init_ver.get("DefaultConfig", {}) + self.create_function_definition_version(func_def.id, init_func_def, init_config) + + return func_def + + def create_function_definition_version( + self, function_definition_id, functions, default_config + ): + + if function_definition_id not in self.function_definitions: + raise IdNotFoundException("That functions definition does not exist.") + + func_ver = FakeFunctionDefinitionVersion( + self.region_name, function_definition_id, functions, default_config + ) + func_vers = self.function_definition_versions.get( + func_ver.function_definition_id, {} + ) + func_vers[func_ver.version] = func_ver + self.function_definition_versions[func_ver.function_definition_id] = func_vers + self.function_definitions[ + function_definition_id + ].latest_version = func_ver.version + self.function_definitions[ + function_definition_id + ].latest_version_arn = func_ver.arn + + return func_ver + greengrass_backends = BackendDict(GreengrassBackend, "greengrass") diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index 49d6ae4a717..079b013617b 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -260,3 +260,18 @@ def create_resource_definition_version(self): resource_definition_id=resource_definition_id, resources=resources ) return 201, {"status": 201}, json.dumps(res.to_dict()) + + def function_definitions(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + + if self.method == "POST": + return self.create_function_definition() + + def create_function_definition(self): + + initial_version = self._get_param("InitialVersion") + name = self._get_param("Name") + res = self.greengrass_backend.create_function_definition( + name=name, initial_version=initial_version + ) + return 201, {"status": 201}, json.dumps(res.to_dict()) diff --git a/moto/greengrass/urls.py b/moto/greengrass/urls.py index 5a237da0a4d..15a2b2bbc06 100644 --- a/moto/greengrass/urls.py +++ b/moto/greengrass/urls.py @@ -17,6 +17,7 @@ "{0}/greengrass/definition/devices/(?P[^/]+)/?$": response.device_definition, "{0}/greengrass/definition/devices/(?P[^/]+)/versions$": response.device_definition_versions, "{0}/greengrass/definition/devices/(?P[^/]+)/versions/(?P[^/]+)/?$": response.device_definition_version, + "{0}/greengrass/definition/functions$": response.function_definitions, "{0}/greengrass/definition/resources$": response.resource_definitions, "{0}/greengrass/definition/resources/(?P[^/]+)/versions$": response.resource_definition_versions, } diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py new file mode 100644 index 00000000000..f8b581bab18 --- /dev/null +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -0,0 +1,41 @@ +import boto3 +import freezegun + +from moto import mock_greengrass +from moto.core import get_account_id +from moto.settings import TEST_SERVER_MODE + +ACCOUNT_ID = get_account_id() + + +@freezegun.freeze_time("2022-06-01 12:00:00") +@mock_greengrass +def test_create_function_definition(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + init_ver = { + "Functions": [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + } + func_name = "TestFunc" + res = client.create_function_definition(InitialVersion=init_ver, Name=func_name) + res.should.have.key("Arn") + res.should.have.key("Id") + res.should.have.key("LatestVersion") + res.should.have.key("LatestVersionArn") + res.should.have.key("Name").equals(func_name) + res["ResponseMetadata"]["HTTPStatusCode"].should.equal(201) + + if not TEST_SERVER_MODE: + res.should.have.key("CreationTimestamp").equals("2022-06-01T12:00:00.000Z") + res.should.have.key("LastUpdatedTimestamp").equals("2022-06-01T12:00:00.000Z") From d7b0aea25180d96760fc31bba65df0c8d9b5e845 Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 13:20:06 +0900 Subject: [PATCH 2/8] Greengrass Implement create_function_definition_version --- moto/greengrass/models.py | 2 +- moto/greengrass/responses.py | 19 +++++ moto/greengrass/urls.py | 1 + .../test_greengrass_functions.py | 77 +++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 77a05a27baf..3e56587766f 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -477,7 +477,7 @@ def create_function_definition_version( ): if function_definition_id not in self.function_definitions: - raise IdNotFoundException("That functions definition does not exist.") + raise IdNotFoundException("That lambdas does not exist.") func_ver = FakeFunctionDefinitionVersion( self.region_name, function_definition_id, functions, default_config diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index 079b013617b..3633cef29f8 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -275,3 +275,22 @@ def create_function_definition(self): name=name, initial_version=initial_version ) return 201, {"status": 201}, json.dumps(res.to_dict()) + + def function_definition_versions(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + + if self.method == "POST": + return self.create_function_definition_version() + + def create_function_definition_version(self): + + default_config = self._get_param("DefaultConfig") + function_definition_id = self.path.split("/")[-2] + functions = self._get_param("Functions") + + res = self.greengrass_backend.create_function_definition_version( + default_config=default_config, + function_definition_id=function_definition_id, + functions=functions, + ) + return 201, {"status": 201}, json.dumps(res.to_dict()) diff --git a/moto/greengrass/urls.py b/moto/greengrass/urls.py index 15a2b2bbc06..b10c8bfdc67 100644 --- a/moto/greengrass/urls.py +++ b/moto/greengrass/urls.py @@ -18,6 +18,7 @@ "{0}/greengrass/definition/devices/(?P[^/]+)/versions$": response.device_definition_versions, "{0}/greengrass/definition/devices/(?P[^/]+)/versions/(?P[^/]+)/?$": response.device_definition_version, "{0}/greengrass/definition/functions$": response.function_definitions, + "{0}/greengrass/definition/functions/(?P[^/]+)/versions$": response.function_definition_versions, "{0}/greengrass/definition/resources$": response.resource_definitions, "{0}/greengrass/definition/resources/(?P[^/]+)/versions$": response.resource_definition_versions, } diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index f8b581bab18..b66423dfc56 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -1,5 +1,8 @@ import boto3 +from botocore.client import ClientError import freezegun +import pytest + from moto import mock_greengrass from moto.core import get_account_id @@ -39,3 +42,77 @@ def test_create_function_definition(): if not TEST_SERVER_MODE: res.should.have.key("CreationTimestamp").equals("2022-06-01T12:00:00.000Z") res.should.have.key("LastUpdatedTimestamp").equals("2022-06-01T12:00:00.000Z") + + +@freezegun.freeze_time("2022-06-01 12:00:00") +@mock_greengrass +def test_create_function_definition_version(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + v1_functions = [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + + initial_version = {"Functions": v1_functions} + func_def_res = client.create_function_definition( + InitialVersion=initial_version, Name="TestFunction" + ) + func_def_id = func_def_res["Id"] + + v2_functions = [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:2", + "Id": "987654321", + "FunctionConfiguration": { + "MemorySize": 128, + "EncodingType": "binary", + "Pinned": False, + "Timeout": 5, + }, + } + ] + + func_def_ver_res = client.create_function_definition_version( + FunctionDefinitionId=func_def_id, Functions=v2_functions + ) + func_def_ver_res.should.have.key("Arn") + func_def_ver_res.should.have.key("CreationTimestamp") + func_def_ver_res.should.have.key("Id").equals(func_def_id) + func_def_ver_res.should.have.key("Version") + + if not TEST_SERVER_MODE: + func_def_ver_res["CreationTimestamp"].should.equal("2022-06-01T12:00:00.000Z") + + +@mock_greengrass +def test_create_function_definition_version_with_invalid_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + functions = [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + with pytest.raises(ClientError) as ex: + client.create_function_definition_version( + FunctionDefinitionId="7b0bdeae-54c7-47cf-9f93-561e672efd9c", + Functions=functions, + ) + ex.value.response["Error"]["Message"].should.equal("That lambdas does not exist.") + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") From cf5210441ea99e85a158e2e9c80a35cbc54a80bc Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 13:31:44 +0900 Subject: [PATCH 3/8] Greengrass Implement list_function_definition_versions --- moto/greengrass/models.py | 5 ++ moto/greengrass/responses.py | 11 ++++ .../test_greengrass_functions.py | 54 +++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 3e56587766f..94ccb69edd6 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -496,5 +496,10 @@ def create_function_definition_version( return func_ver + def list_function_definition_versions(self, function_definition_id): + if function_definition_id not in self.function_definition_versions: + raise IdNotFoundException("That lambdas definition does not exist.") + return self.function_definition_versions[function_definition_id] + greengrass_backends = BackendDict(GreengrassBackend, "greengrass") diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index 3633cef29f8..5a739560db8 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -282,6 +282,9 @@ def function_definition_versions(self, request, full_url, headers): if self.method == "POST": return self.create_function_definition_version() + if self.method == "GET": + return self.list_function_definition_versions() + def create_function_definition_version(self): default_config = self._get_param("DefaultConfig") @@ -294,3 +297,11 @@ def create_function_definition_version(self): functions=functions, ) return 201, {"status": 201}, json.dumps(res.to_dict()) + + def list_function_definition_versions(self): + function_definition_id = self.path.split("/")[-2] + res = self.greengrass_backend.list_function_definition_versions( + function_definition_id=function_definition_id + ) + versions = [i.to_dict() for i in res.values()] + return 200, {"status": 200}, json.dumps({"Versions": versions}) diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index b66423dfc56..78924b1d9c2 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -116,3 +116,57 @@ def test_create_function_definition_version_with_invalid_id(): ) ex.value.response["Error"]["Message"].should.equal("That lambdas does not exist.") ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") + + +@freezegun.freeze_time("2022-06-01 12:00:00") +@mock_greengrass +def test_list_function_definition_versions(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + functions = [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + + initial_version = {"Functions": functions} + create_res = client.create_function_definition( + InitialVersion=initial_version, Name="TestFunction" + ) + func_def_id = create_res["Id"] + + func_def_vers_res = client.list_function_definition_versions( + FunctionDefinitionId=func_def_id + ) + + func_def_vers_res.should.have.key("Versions") + device_def_ver = func_def_vers_res["Versions"][0] + device_def_ver.should.have.key("Arn") + device_def_ver.should.have.key("CreationTimestamp") + + if not TEST_SERVER_MODE: + device_def_ver["CreationTimestamp"].should.equal("2022-06-01T12:00:00.000Z") + device_def_ver.should.have.key("Id").equals(func_def_id) + device_def_ver.should.have.key("Version") + + +@mock_greengrass +def test_list_function_definition_versions_with_invalid_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + + with pytest.raises(ClientError) as ex: + client.list_function_definition_versions( + FunctionDefinitionId="7b0bdeae-54c7-47cf-9f93-561e672efd9c" + ) + ex.value.response["Error"]["Message"].should.equal( + "That lambdas definition does not exist." + ) + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") From f89066a43b0b7adc36638f0bb1a0dc0811e7ed75 Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 13:51:30 +0900 Subject: [PATCH 4/8] Greengrass Implement get_function_definition_version --- moto/greengrass/models.py | 19 ++++ moto/greengrass/responses.py | 15 +++ moto/greengrass/urls.py | 1 + .../test_greengrass_functions.py | 92 +++++++++++++++++++ 4 files changed, 127 insertions(+) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 94ccb69edd6..055b6968dc7 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -501,5 +501,24 @@ def list_function_definition_versions(self, function_definition_id): raise IdNotFoundException("That lambdas definition does not exist.") return self.function_definition_versions[function_definition_id] + def get_function_definition_version( + self, function_definition_id, function_definition_version_id + ): + + if function_definition_id not in self.function_definition_versions: + raise IdNotFoundException("That lambdas definition does not exist.") + + if ( + function_definition_version_id + not in self.function_definition_versions[function_definition_id] + ): + raise IdNotFoundException( + f"Version {function_definition_version_id} of Lambda List Definition {function_definition_id} does not exist." + ) + + return self.function_definition_versions[function_definition_id][ + function_definition_version_id + ] + greengrass_backends = BackendDict(GreengrassBackend, "greengrass") diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index 5a739560db8..a98c47c7a6e 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -305,3 +305,18 @@ def list_function_definition_versions(self): ) versions = [i.to_dict() for i in res.values()] return 200, {"status": 200}, json.dumps({"Versions": versions}) + + def function_definition_version(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + + if self.method == "GET": + return self.get_function_definition_version() + + def get_function_definition_version(self): + function_definition_id = self.path.split("/")[-3] + function_definition_version_id = self.path.split("/")[-1] + res = self.greengrass_backend.get_function_definition_version( + function_definition_id=function_definition_id, + function_definition_version_id=function_definition_version_id, + ) + return 200, {"status": 200}, json.dumps(res.to_dict()) diff --git a/moto/greengrass/urls.py b/moto/greengrass/urls.py index b10c8bfdc67..83a51afb1c6 100644 --- a/moto/greengrass/urls.py +++ b/moto/greengrass/urls.py @@ -19,6 +19,7 @@ "{0}/greengrass/definition/devices/(?P[^/]+)/versions/(?P[^/]+)/?$": response.device_definition_version, "{0}/greengrass/definition/functions$": response.function_definitions, "{0}/greengrass/definition/functions/(?P[^/]+)/versions$": response.function_definition_versions, + "{0}/greengrass/definition/functions/(?P[^/]+)/versions/(?P[^/]+)/?$": response.function_definition_version, "{0}/greengrass/definition/resources$": response.resource_definitions, "{0}/greengrass/definition/resources/(?P[^/]+)/versions$": response.resource_definition_versions, } diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index 78924b1d9c2..f38294e3952 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -170,3 +170,95 @@ def test_list_function_definition_versions_with_invalid_id(): "That lambdas definition does not exist." ) ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") + + +@freezegun.freeze_time("2022-06-01 12:00:00") +@mock_greengrass +def test_get_function_definition_version(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + functions = [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + + initial_version = {"Functions": functions} + create_res = client.create_function_definition( + InitialVersion=initial_version, Name="TestFunction" + ) + + func_def_id = create_res["Id"] + func_def_ver_id = create_res["LatestVersion"] + + func_def_ver_res = client.get_function_definition_version( + FunctionDefinitionId=func_def_id, FunctionDefinitionVersionId=func_def_ver_id + ) + + func_def_ver_res.should.have.key("Arn") + func_def_ver_res.should.have.key("CreationTimestamp") + func_def_ver_res.should.have.key("Definition").should.equal(initial_version) + func_def_ver_res.should.have.key("Id").equals(func_def_id) + func_def_ver_res.should.have.key("Version") + + if not TEST_SERVER_MODE: + func_def_ver_res["CreationTimestamp"].should.equal("2022-06-01T12:00:00.000Z") + + +@mock_greengrass +def test_get_function_definition_version_with_invalid_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + + with pytest.raises(ClientError) as ex: + client.get_function_definition_version( + FunctionDefinitionId="7b0bdeae-54c7-47cf-9f93-561e672efd9c", + FunctionDefinitionVersionId="7b0bdeae-54c7-47cf-9f93-561e672efd9c", + ) + ex.value.response["Error"]["Message"].should.equal( + "That lambdas definition does not exist." + ) + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") + + +@mock_greengrass +def test_get_function_definition_version_with_invalid_version_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + functions = [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + + initial_version = {"Functions": functions} + create_res = client.create_function_definition( + InitialVersion=initial_version, Name="TestFunction" + ) + + func_def_id = create_res["Id"] + invalid_func_def_ver_id = "7b0bdeae-54c7-47cf-9f93-561e672efd9c" + + with pytest.raises(ClientError) as ex: + client.get_function_definition_version( + FunctionDefinitionId=func_def_id, + FunctionDefinitionVersionId=invalid_func_def_ver_id, + ) + ex.value.response["Error"]["Message"].should.equal( + f"Version {invalid_func_def_ver_id} of Lambda List Definition {func_def_id} does not exist." + ) + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") From e6d479b4661060887de6c1b3cf09f63e7334bd62 Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 14:11:54 +0900 Subject: [PATCH 5/8] Greengrass Implement list_function_definitions --- moto/greengrass/models.py | 3 ++ moto/greengrass/responses.py | 13 +++++++ .../test_greengrass_functions.py | 37 +++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 055b6968dc7..9318b5fa9cb 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -472,6 +472,9 @@ def create_function_definition(self, name, initial_version): return func_def + def list_function_definitions(self): + return self.function_definitions.values() + def create_function_definition_version( self, function_definition_id, functions, default_config ): diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index a98c47c7a6e..34e1ea8c322 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -267,6 +267,9 @@ def function_definitions(self, request, full_url, headers): if self.method == "POST": return self.create_function_definition() + if self.method == "GET": + return self.list_function_definitions() + def create_function_definition(self): initial_version = self._get_param("InitialVersion") @@ -276,6 +279,16 @@ def create_function_definition(self): ) return 201, {"status": 201}, json.dumps(res.to_dict()) + def list_function_definitions(self): + res = self.greengrass_backend.list_function_definitions() + return ( + 200, + {"status": 200}, + json.dumps( + {"Definitions": [func_definition.to_dict() for func_definition in res]} + ), + ) + def function_definition_versions(self, request, full_url, headers): self.setup_class(request, full_url, headers) diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index f38294e3952..08033b5fdfe 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -44,6 +44,43 @@ def test_create_function_definition(): res.should.have.key("LastUpdatedTimestamp").equals("2022-06-01T12:00:00.000Z") +@freezegun.freeze_time("2022-06-01 12:00:00") +@mock_greengrass +def test_list_function_definitions(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + init_ver = { + "Functions": [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + } + func_name = "TestFunc" + client.create_function_definition(InitialVersion=init_ver, Name=func_name) + + res = client.list_function_definitions() + func_def = res["Definitions"][0] + + func_def.should.have.key("Name").equals(func_name) + func_def.should.have.key("Arn") + func_def.should.have.key("Id") + func_def.should.have.key("LatestVersion") + func_def.should.have.key("LatestVersionArn") + if not TEST_SERVER_MODE: + func_def.should.have.key("CreationTimestamp").equal("2022-06-01T12:00:00.000Z") + func_def.should.have.key("LastUpdatedTimestamp").equals( + "2022-06-01T12:00:00.000Z" + ) + + @freezegun.freeze_time("2022-06-01 12:00:00") @mock_greengrass def test_create_function_definition_version(): From a50828701fca369f640d34da84943812c53ad7d9 Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 14:24:41 +0900 Subject: [PATCH 6/8] Greengrass Implement get_function_definition --- moto/greengrass/models.py | 6 ++ moto/greengrass/responses.py | 13 ++++ moto/greengrass/urls.py | 1 + .../test_greengrass_functions.py | 59 +++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 9318b5fa9cb..fbc97a7adc4 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -475,6 +475,12 @@ def create_function_definition(self, name, initial_version): def list_function_definitions(self): return self.function_definitions.values() + def get_function_definition(self, function_definition_id): + + if function_definition_id not in self.function_definitions: + raise IdNotFoundException("That Lambda List Definition does not exist.") + return self.function_definitions[function_definition_id] + def create_function_definition_version( self, function_definition_id, functions, default_config ): diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index 34e1ea8c322..f3dd913b4db 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -289,6 +289,19 @@ def list_function_definitions(self): ), ) + def function_definition(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + + if self.method == "GET": + return self.get_function_definition() + + def get_function_definition(self): + function_definition_id = self.path.split("/")[-1] + res = self.greengrass_backend.get_function_definition( + function_definition_id=function_definition_id, + ) + return 200, {"status": 200}, json.dumps(res.to_dict()) + def function_definition_versions(self, request, full_url, headers): self.setup_class(request, full_url, headers) diff --git a/moto/greengrass/urls.py b/moto/greengrass/urls.py index 83a51afb1c6..1ce85893cc0 100644 --- a/moto/greengrass/urls.py +++ b/moto/greengrass/urls.py @@ -18,6 +18,7 @@ "{0}/greengrass/definition/devices/(?P[^/]+)/versions$": response.device_definition_versions, "{0}/greengrass/definition/devices/(?P[^/]+)/versions/(?P[^/]+)/?$": response.device_definition_version, "{0}/greengrass/definition/functions$": response.function_definitions, + "{0}/greengrass/definition/functions/(?P[^/]+)/?$": response.function_definition, "{0}/greengrass/definition/functions/(?P[^/]+)/versions$": response.function_definition_versions, "{0}/greengrass/definition/functions/(?P[^/]+)/versions/(?P[^/]+)/?$": response.function_definition_version, "{0}/greengrass/definition/resources$": response.resource_definitions, diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index 08033b5fdfe..41a7f50a2f7 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -81,6 +81,65 @@ def test_list_function_definitions(): ) +@freezegun.freeze_time("2022-06-01 12:00:00") +@mock_greengrass +def test_get_function_definition(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + init_ver = { + "Functions": [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + } + func_name = "TestFunc" + create_res = client.create_function_definition( + InitialVersion=init_ver, Name=func_name + ) + + func_def_id = create_res["Id"] + arn = create_res["Arn"] + latest_version = create_res["LatestVersion"] + latest_version_arn = create_res["LatestVersionArn"] + + get_res = client.get_function_definition(FunctionDefinitionId=func_def_id) + + get_res.should.have.key("Name").equals(func_name) + get_res.should.have.key("Arn").equals(arn) + get_res.should.have.key("Id").equals(func_def_id) + get_res.should.have.key("LatestVersion").equals(latest_version) + get_res.should.have.key("LatestVersionArn").equals(latest_version_arn) + get_res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) + + if not TEST_SERVER_MODE: + get_res.should.have.key("CreationTimestamp").equal("2022-06-01T12:00:00.000Z") + get_res.should.have.key("LastUpdatedTimestamp").equals( + "2022-06-01T12:00:00.000Z" + ) + + +@mock_greengrass +def test_get_function_definition_with_invalid_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + with pytest.raises(ClientError) as ex: + client.get_function_definition( + FunctionDefinitionId="b552443b-1888-469b-81f8-0ebc5ca92949" + ) + ex.value.response["Error"]["Message"].should.equal( + "That Lambda List Definition does not exist." + ) + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") + + @freezegun.freeze_time("2022-06-01 12:00:00") @mock_greengrass def test_create_function_definition_version(): From 915e1c211750f2f278b56a016864fe2c5e35814b Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 14:29:48 +0900 Subject: [PATCH 7/8] Greengrass Implement delete_function_definition --- moto/greengrass/models.py | 6 +++ moto/greengrass/responses.py | 10 +++++ .../test_greengrass_functions.py | 42 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index fbc97a7adc4..4d64b745817 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -481,6 +481,12 @@ def get_function_definition(self, function_definition_id): raise IdNotFoundException("That Lambda List Definition does not exist.") return self.function_definitions[function_definition_id] + def delete_function_definition(self, function_definition_id): + if function_definition_id not in self.function_definitions: + raise IdNotFoundException("That lambdas definition does not exist.") + del self.function_definitions[function_definition_id] + del self.function_definition_versions[function_definition_id] + def create_function_definition_version( self, function_definition_id, functions, default_config ): diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index f3dd913b4db..554d6e3c5b5 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -295,6 +295,9 @@ def function_definition(self, request, full_url, headers): if self.method == "GET": return self.get_function_definition() + if self.method == "DELETE": + return self.delete_function_definition() + def get_function_definition(self): function_definition_id = self.path.split("/")[-1] res = self.greengrass_backend.get_function_definition( @@ -302,6 +305,13 @@ def get_function_definition(self): ) return 200, {"status": 200}, json.dumps(res.to_dict()) + def delete_function_definition(self): + function_definition_id = self.path.split("/")[-1] + self.greengrass_backend.delete_function_definition( + function_definition_id=function_definition_id, + ) + return 200, {"status": 200}, json.dumps({}) + def function_definition_versions(self, request, full_url, headers): self.setup_class(request, full_url, headers) diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index 41a7f50a2f7..b2037a938a8 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -140,6 +140,48 @@ def test_get_function_definition_with_invalid_id(): ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") +@mock_greengrass +def test_delete_function_definition(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + init_ver = { + "Functions": [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + } + create_res = client.create_function_definition( + InitialVersion=init_ver, Name="TestFunc" + ) + + func_def_id = create_res["Id"] + del_res = client.delete_function_definition(FunctionDefinitionId=func_def_id) + del_res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) + + +@mock_greengrass +def test_delete_function_definition_with_invalid_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + + with pytest.raises(ClientError) as ex: + client.delete_function_definition( + FunctionDefinitionId="6fbffc21-989e-4d29-a793-a42f450a78c6" + ) + ex.value.response["Error"]["Message"].should.equal( + "That lambdas definition does not exist." + ) + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") + + @freezegun.freeze_time("2022-06-01 12:00:00") @mock_greengrass def test_create_function_definition_version(): From 49c2fea33fb23fdda0f0cd1c1ebd846cac835e16 Mon Sep 17 00:00:00 2001 From: Tomoya Iwata Date: Thu, 16 Jun 2022 14:45:32 +0900 Subject: [PATCH 8/8] Greengrass Implement update_function_definition --- moto/greengrass/models.py | 10 +++ moto/greengrass/responses.py | 11 +++ .../test_greengrass_functions.py | 82 +++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/moto/greengrass/models.py b/moto/greengrass/models.py index 4d64b745817..9041abac1bf 100644 --- a/moto/greengrass/models.py +++ b/moto/greengrass/models.py @@ -487,6 +487,16 @@ def delete_function_definition(self, function_definition_id): del self.function_definitions[function_definition_id] del self.function_definition_versions[function_definition_id] + def update_function_definition(self, function_definition_id, name): + + if name == "": + raise InvalidContainerDefinitionException( + "Input does not contain any attributes to be updated" + ) + if function_definition_id not in self.function_definitions: + raise IdNotFoundException("That lambdas definition does not exist.") + self.function_definitions[function_definition_id].name = name + def create_function_definition_version( self, function_definition_id, functions, default_config ): diff --git a/moto/greengrass/responses.py b/moto/greengrass/responses.py index 554d6e3c5b5..fed4a8b3b14 100644 --- a/moto/greengrass/responses.py +++ b/moto/greengrass/responses.py @@ -298,6 +298,9 @@ def function_definition(self, request, full_url, headers): if self.method == "DELETE": return self.delete_function_definition() + if self.method == "PUT": + return self.update_function_definition() + def get_function_definition(self): function_definition_id = self.path.split("/")[-1] res = self.greengrass_backend.get_function_definition( @@ -312,6 +315,14 @@ def delete_function_definition(self): ) return 200, {"status": 200}, json.dumps({}) + def update_function_definition(self): + function_definition_id = self.path.split("/")[-1] + name = self._get_param("Name") + self.greengrass_backend.update_function_definition( + function_definition_id=function_definition_id, name=name + ) + return 200, {"status": 200}, json.dumps({}) + def function_definition_versions(self, request, full_url, headers): self.setup_class(request, full_url, headers) diff --git a/tests/test_greengrass/test_greengrass_functions.py b/tests/test_greengrass/test_greengrass_functions.py index b2037a938a8..39a614de727 100644 --- a/tests/test_greengrass/test_greengrass_functions.py +++ b/tests/test_greengrass/test_greengrass_functions.py @@ -182,6 +182,88 @@ def test_delete_function_definition_with_invalid_id(): ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") +@mock_greengrass +def test_update_function_definition(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + init_ver = { + "Functions": [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + } + create_res = client.create_function_definition( + InitialVersion=init_ver, Name="TestFunc" + ) + + func_def_id = create_res["Id"] + updated_func_name = "UpdatedFunction" + update_res = client.update_function_definition( + FunctionDefinitionId=func_def_id, Name=updated_func_name + ) + update_res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) + + get_res = client.get_function_definition(FunctionDefinitionId=func_def_id) + get_res.should.have.key("Name").equals(updated_func_name) + + +@mock_greengrass +def test_update_function_definition_with_empty_name(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + init_ver = { + "Functions": [ + { + "FunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:test-func:1", + "Id": "1234567890", + "FunctionConfiguration": { + "MemorySize": 16384, + "EncodingType": "binary", + "Pinned": True, + "Timeout": 3, + }, + } + ] + } + create_res = client.create_function_definition( + InitialVersion=init_ver, Name="TestFunc" + ) + + func_def_id = create_res["Id"] + + with pytest.raises(ClientError) as ex: + client.update_function_definition(FunctionDefinitionId=func_def_id, Name="") + ex.value.response["Error"]["Message"].should.equal( + "Input does not contain any attributes to be updated" + ) + ex.value.response["Error"]["Code"].should.equal( + "InvalidContainerDefinitionException" + ) + + +@mock_greengrass +def test_update_function_definition_with_invalid_id(): + + client = boto3.client("greengrass", region_name="ap-northeast-1") + + with pytest.raises(ClientError) as ex: + client.update_function_definition( + FunctionDefinitionId="6fbffc21-989e-4d29-a793-a42f450a78c6", Name="123" + ) + ex.value.response["Error"]["Message"].should.equal( + "That lambdas definition does not exist." + ) + ex.value.response["Error"]["Code"].should.equal("IdNotFoundException") + + @freezegun.freeze_time("2022-06-01 12:00:00") @mock_greengrass def test_create_function_definition_version():