Skip to content

Commit

Permalink
Greengrass Implement resource_definition APIs (#5235)
Browse files Browse the repository at this point in the history
  • Loading branch information
cm-iwata committed Jun 16, 2022
1 parent c3f0606 commit 6272d58
Show file tree
Hide file tree
Showing 5 changed files with 307 additions and 0 deletions.
6 changes: 6 additions & 0 deletions moto/greengrass/exceptions.py
Expand Up @@ -21,3 +21,9 @@ class VersionNotFoundException(GreengrassClientError):
def __init__(self, msg):
self.code = 404
super().__init__("VersionNotFoundException", msg)


class InvalidInputException(GreengrassClientError):
def __init__(self, msg):
self.code = 400
super().__init__("InvalidInputException", msg)
24 changes: 24 additions & 0 deletions moto/greengrass/models.py
Expand Up @@ -7,6 +7,7 @@
from .exceptions import (
GreengrassClientError,
IdNotFoundException,
InvalidInputException,
InvalidContainerDefinitionException,
VersionNotFoundException,
)
Expand Down Expand Up @@ -354,6 +355,29 @@ def create_resource_definition(self, name, initial_version):

return resource_def

def list_resource_definitions(self):
return self.resource_definitions

def get_resource_definition(self, resource_definition_id):

if resource_definition_id not in self.resource_definitions:
raise IdNotFoundException("That Resource List Definition does not exist.")
return self.resource_definitions[resource_definition_id]

def delete_resource_definition(self, resource_definition_id):
if resource_definition_id not in self.resource_definitions:
raise IdNotFoundException("That resources definition does not exist.")
del self.resource_definitions[resource_definition_id]
del self.resource_definition_versions[resource_definition_id]

def update_resource_definition(self, resource_definition_id, name):

if name == "":
raise InvalidInputException("Invalid resource name.")
if resource_definition_id not in self.resource_definitions:
raise IdNotFoundException("That resources definition does not exist.")
self.resource_definitions[resource_definition_id].name = name

def create_resource_definition_version(self, resource_definition_id, resources):

if resource_definition_id not in self.resource_definitions:
Expand Down
48 changes: 48 additions & 0 deletions moto/greengrass/responses.py
Expand Up @@ -236,6 +236,9 @@ def resource_definitions(self, request, full_url, headers):
if self.method == "POST":
return self.create_resource_definition()

if self.method == "GET":
return self.list_resource_definitions()

def create_resource_definition(self):

initial_version = self._get_param("InitialVersion")
Expand All @@ -245,6 +248,51 @@ def create_resource_definition(self):
)
return 201, {"status": 201}, json.dumps(res.to_dict())

def list_resource_definitions(self):

res = self.greengrass_backend.list_resource_definitions()
return (
200,
{"status": 200},
json.dumps({"Definitions": [i.to_dict() for i in res.values()]}),
)

def resource_definition(self, request, full_url, headers):
self.setup_class(request, full_url, headers)

if self.method == "GET":
return self.get_resource_definition()

if self.method == "DELETE":
return self.delete_resource_definition()

if self.method == "PUT":
return self.update_resource_definition()

def get_resource_definition(self):
resource_definition_id = self.path.split("/")[-1]
res = self.greengrass_backend.get_resource_definition(
resource_definition_id=resource_definition_id
)
return 200, {"status": 200}, json.dumps(res.to_dict())

def delete_resource_definition(self):

resource_definition_id = self.path.split("/")[-1]
self.greengrass_backend.delete_resource_definition(
resource_definition_id=resource_definition_id
)
return 200, {"status": 200}, json.dumps({})

def update_resource_definition(self):

resource_definition_id = self.path.split("/")[-1]
name = self._get_param("Name")
self.greengrass_backend.update_resource_definition(
resource_definition_id=resource_definition_id, name=name
)
return 200, {"status": 200}, json.dumps({})

def resource_definition_versions(self, request, full_url, headers):
self.setup_class(request, full_url, headers)

Expand Down
1 change: 1 addition & 0 deletions moto/greengrass/urls.py
Expand Up @@ -18,5 +18,6 @@
"{0}/greengrass/definition/devices/(?P<definition_id>[^/]+)/versions$": response.device_definition_versions,
"{0}/greengrass/definition/devices/(?P<definition_id>[^/]+)/versions/(?P<definition_version_id>[^/]+)/?$": response.device_definition_version,
"{0}/greengrass/definition/resources$": response.resource_definitions,
"{0}/greengrass/definition/resources/(?P<definition_id>[^/]+)/?$": response.resource_definition,
"{0}/greengrass/definition/resources/(?P<definition_id>[^/]+)/versions$": response.resource_definition_versions,
}
228 changes: 228 additions & 0 deletions tests/test_greengrass/test_greengrass_resource.py
Expand Up @@ -270,3 +270,231 @@ def test_create_resources_definition_version_with_invalid_local_device_resource(
f", but got: {source_path}])"
)
ex.value.response["Error"]["Code"].should.equal("400")


@freezegun.freeze_time("2022-06-01 12:00:00")
@mock_greengrass
def test_list_resources():
client = boto3.client("greengrass", region_name="ap-northeast-1")
init_ver = {
"Resources": [
{
"Id": "123",
"Name": "test_directory",
"ResourceDataContainer": {
"LocalVolumeResourceData": {
"DestinationPath": "/test_dir",
"GroupOwnerSetting": {"AutoAddGroupOwner": True},
"SourcePath": "/home/ggc_user/test_dir",
}
},
}
]
}
resource_name = "MotoTestResource"
create_res = client.create_resource_definition(
InitialVersion=init_ver, Name=resource_name
)

res_def_id = create_res["Id"]
res_def_arn = create_res["Arn"]
res_ver = create_res["LatestVersion"]
res_ver_arn = create_res["LatestVersionArn"]

res = client.list_resource_definitions()
res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
res.should.have.key("Definitions")
res["Definitions"].should.have.length_of(1)
definition = res["Definitions"][0]
definition.should.have.key("Id").equals(res_def_id)
definition.should.have.key("Arn").equals(res_def_arn)
definition.should.have.key("LatestVersion").equals(res_ver)
definition.should.have.key("LatestVersionArn").equals(res_ver_arn)

if not TEST_SERVER_MODE:
definition.should.have.key("CreationTimestamp").equals(
"2022-06-01T12:00:00.000Z"
)
definition.should.have.key("LastUpdatedTimestamp").equals(
"2022-06-01T12:00:00.000Z"
)


@freezegun.freeze_time("2022-06-01 12:00:00")
@mock_greengrass
def test_get_resource_definition():

client = boto3.client("greengrass", region_name="ap-northeast-1")
init_ver = {
"Resources": [
{
"Id": "123",
"Name": "test_directory",
"ResourceDataContainer": {
"LocalVolumeResourceData": {
"DestinationPath": "/test_dir",
"GroupOwnerSetting": {"AutoAddGroupOwner": True},
"SourcePath": "/home/ggc_user/test_dir",
}
},
}
]
}
resource_name = "MotoTestResource"
create_res = client.create_resource_definition(
InitialVersion=init_ver, Name=resource_name
)

resource_def_id = create_res["Id"]
arn = create_res["Arn"]
latest_version = create_res["LatestVersion"]
latest_version_arn = create_res["LatestVersionArn"]

get_res = client.get_resource_definition(ResourceDefinitionId=resource_def_id)

get_res.should.have.key("Name").equals(resource_name)
get_res.should.have.key("Arn").equals(arn)
get_res.should.have.key("Id").equals(resource_def_id)
get_res.should.have.key("LatestVersion").equals(latest_version)
get_res.should.have.key("LatestVersionArn").equals(latest_version_arn)

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_resource_definition_with_invalid_id():

client = boto3.client("greengrass", region_name="ap-northeast-1")
with pytest.raises(ClientError) as ex:
client.get_resource_definition(
ResourceDefinitionId="76f22a66-176a-4474-b450-04099dc4b069"
)
ex.value.response["Error"]["Message"].should.equal(
"That Resource List Definition does not exist."
)
ex.value.response["Error"]["Code"].should.equal("IdNotFoundException")


@mock_greengrass
def test_delete_resource_definition():

client = boto3.client("greengrass", region_name="ap-northeast-1")
init_ver = {
"Resources": [
{
"Id": "123",
"Name": "test_directory",
"ResourceDataContainer": {
"LocalVolumeResourceData": {
"DestinationPath": "/test_dir",
"GroupOwnerSetting": {"AutoAddGroupOwner": True},
"SourcePath": "/home/ggc_user/test_dir",
}
},
}
]
}
create_res = client.create_resource_definition(
InitialVersion=init_ver, Name="TestResource"
)

resource_def_id = create_res["Id"]
del_res = client.delete_resource_definition(ResourceDefinitionId=resource_def_id)
del_res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)


@mock_greengrass
def test_delete_resource_definition_with_invalid_id():

client = boto3.client("greengrass", region_name="ap-northeast-1")

with pytest.raises(ClientError) as ex:
client.delete_resource_definition(
ResourceDefinitionId="6fbffc21-989e-4d29-a793-a42f450a78c6"
)
ex.value.response["Error"]["Message"].should.equal(
"That resources definition does not exist."
)
ex.value.response["Error"]["Code"].should.equal("IdNotFoundException")


@mock_greengrass
def test_update_resource_definition():

client = boto3.client("greengrass", region_name="ap-northeast-1")
init_ver = {
"Resources": [
{
"Id": "123",
"Name": "test_directory",
"ResourceDataContainer": {
"LocalVolumeResourceData": {
"DestinationPath": "/test_dir",
"GroupOwnerSetting": {"AutoAddGroupOwner": True},
"SourcePath": "/home/ggc_user/test_dir",
}
},
}
]
}
create_res = client.create_resource_definition(
InitialVersion=init_ver, Name="TestResource"
)
resource_def_id = create_res["Id"]
updated_resource_name = "UpdatedResource"
update_res = client.update_resource_definition(
ResourceDefinitionId=resource_def_id, Name=updated_resource_name
)
update_res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)

get_res = client.get_resource_definition(ResourceDefinitionId=resource_def_id)
get_res.should.have.key("Name").equals(updated_resource_name)


@mock_greengrass
def test_update_device_definition_with_empty_name():

client = boto3.client("greengrass", region_name="ap-northeast-1")
init_ver = {
"Resources": [
{
"Id": "123",
"Name": "test_directory",
"ResourceDataContainer": {
"LocalVolumeResourceData": {
"DestinationPath": "/test_dir",
"GroupOwnerSetting": {"AutoAddGroupOwner": True},
"SourcePath": "/home/ggc_user/test_dir",
}
},
}
]
}
create_res = client.create_resource_definition(
InitialVersion=init_ver, Name="TestResource"
)
resource_def_id = create_res["Id"]

with pytest.raises(ClientError) as ex:
client.update_resource_definition(ResourceDefinitionId=resource_def_id, Name="")
ex.value.response["Error"]["Message"].should.equal("Invalid resource name.")
ex.value.response["Error"]["Code"].should.equal("InvalidInputException")


@mock_greengrass
def test_update_resource_definition_with_invalid_id():

client = boto3.client("greengrass", region_name="ap-northeast-1")

with pytest.raises(ClientError) as ex:
client.update_resource_definition(
ResourceDefinitionId="6fbffc21-989e-4d29-a793-a42f450a78c6", Name="123"
)
ex.value.response["Error"]["Message"].should.equal(
"That resources definition does not exist."
)
ex.value.response["Error"]["Code"].should.equal("IdNotFoundException")

0 comments on commit 6272d58

Please sign in to comment.