Greengrass Implement group and role associate APIs (#5278)
This commit is contained in:
parent
6282e5124d
commit
01d0141da8
@ -361,10 +361,25 @@ class FakeGroupVersion(BaseModel):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
class FakeAssociatedRole(BaseModel):
|
||||||
|
def __init__(self, role_arn):
|
||||||
|
self.role_arn = role_arn
|
||||||
|
self.associated_at = datetime.utcnow()
|
||||||
|
|
||||||
|
def to_dict(self, include_detail=False):
|
||||||
|
|
||||||
|
obj = {"AssociatedAt": iso_8601_datetime_with_milliseconds(self.associated_at)}
|
||||||
|
if include_detail:
|
||||||
|
obj["RoleArn"] = self.role_arn
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
class GreengrassBackend(BaseBackend):
|
class GreengrassBackend(BaseBackend):
|
||||||
def __init__(self, region_name, account_id):
|
def __init__(self, region_name, account_id):
|
||||||
super().__init__(region_name, account_id)
|
super().__init__(region_name, account_id)
|
||||||
self.groups = OrderedDict()
|
self.groups = OrderedDict()
|
||||||
|
self.group_role_associations = OrderedDict()
|
||||||
self.group_versions = OrderedDict()
|
self.group_versions = OrderedDict()
|
||||||
self.core_definitions = OrderedDict()
|
self.core_definitions = OrderedDict()
|
||||||
self.core_definition_versions = OrderedDict()
|
self.core_definition_versions = OrderedDict()
|
||||||
@ -1066,5 +1081,28 @@ class GreengrassBackend(BaseBackend):
|
|||||||
|
|
||||||
return self.group_versions[group_id][group_version_id]
|
return self.group_versions[group_id][group_version_id]
|
||||||
|
|
||||||
|
def associate_role_to_group(self, group_id, role_arn):
|
||||||
|
|
||||||
|
# I don't know why, AssociateRoleToGroup does not check specified group is exists
|
||||||
|
# So, this API allows any group id such as "a"
|
||||||
|
|
||||||
|
associated_role = FakeAssociatedRole(role_arn)
|
||||||
|
self.group_role_associations[group_id] = associated_role
|
||||||
|
return associated_role
|
||||||
|
|
||||||
|
def get_associated_role(self, group_id):
|
||||||
|
|
||||||
|
if group_id not in self.group_role_associations:
|
||||||
|
raise GreengrassClientError(
|
||||||
|
"404", "You need to attach an IAM role to this deployment group."
|
||||||
|
)
|
||||||
|
|
||||||
|
return self.group_role_associations[group_id]
|
||||||
|
|
||||||
|
def disassociate_role_from_group(self, group_id):
|
||||||
|
if group_id not in self.group_role_associations:
|
||||||
|
return
|
||||||
|
del self.group_role_associations[group_id]
|
||||||
|
|
||||||
|
|
||||||
greengrass_backends = BackendDict(GreengrassBackend, "greengrass")
|
greengrass_backends = BackendDict(GreengrassBackend, "greengrass")
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from moto.core.utils import iso_8601_datetime_with_milliseconds
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from .models import greengrass_backends
|
from .models import greengrass_backends
|
||||||
|
|
||||||
@ -677,3 +679,50 @@ class GreengrassResponse(BaseResponse):
|
|||||||
group_version_id=group_version_id,
|
group_version_id=group_version_id,
|
||||||
)
|
)
|
||||||
return 200, {"status": 200}, json.dumps(res.to_dict(include_detail=True))
|
return 200, {"status": 200}, json.dumps(res.to_dict(include_detail=True))
|
||||||
|
|
||||||
|
def role(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
|
if self.method == "PUT":
|
||||||
|
return self.associate_role_to_group()
|
||||||
|
|
||||||
|
if self.method == "GET":
|
||||||
|
return self.get_associated_role()
|
||||||
|
|
||||||
|
if self.method == "DELETE":
|
||||||
|
return self.disassociate_role_from_group()
|
||||||
|
|
||||||
|
def associate_role_to_group(self):
|
||||||
|
|
||||||
|
group_id = self.path.split("/")[-2]
|
||||||
|
role_arn = self._get_param("RoleArn")
|
||||||
|
res = self.greengrass_backend.associate_role_to_group(
|
||||||
|
group_id=group_id,
|
||||||
|
role_arn=role_arn,
|
||||||
|
)
|
||||||
|
return 200, {"status": 200}, json.dumps(res.to_dict())
|
||||||
|
|
||||||
|
def get_associated_role(self):
|
||||||
|
|
||||||
|
group_id = self.path.split("/")[-2]
|
||||||
|
res = self.greengrass_backend.get_associated_role(
|
||||||
|
group_id=group_id,
|
||||||
|
)
|
||||||
|
return 200, {"status": 200}, json.dumps(res.to_dict(include_detail=True))
|
||||||
|
|
||||||
|
def disassociate_role_from_group(self):
|
||||||
|
group_id = self.path.split("/")[-2]
|
||||||
|
self.greengrass_backend.disassociate_role_from_group(
|
||||||
|
group_id=group_id,
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
200,
|
||||||
|
{"status": 200},
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"DisassociatedAt": iso_8601_datetime_with_milliseconds(
|
||||||
|
datetime.utcnow()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@ -31,6 +31,7 @@ url_paths = {
|
|||||||
"{0}/greengrass/definition/resources/(?P<definition_id>[^/]+)/versions/(?P<definition_version_id>[^/]+)/?$": response.resource_definition_version,
|
"{0}/greengrass/definition/resources/(?P<definition_id>[^/]+)/versions/(?P<definition_version_id>[^/]+)/?$": response.resource_definition_version,
|
||||||
"{0}/greengrass/groups$": response.groups,
|
"{0}/greengrass/groups$": response.groups,
|
||||||
"{0}/greengrass/groups/(?P<group_id>[^/]+)/?$": response.group,
|
"{0}/greengrass/groups/(?P<group_id>[^/]+)/?$": response.group,
|
||||||
|
"{0}/greengrass/groups/(?P<group_id>[^/]+)/role$": response.role,
|
||||||
"{0}/greengrass/groups/(?P<group_id>[^/]+)/versions$": response.group_versions,
|
"{0}/greengrass/groups/(?P<group_id>[^/]+)/versions$": response.group_versions,
|
||||||
"{0}/greengrass/groups/(?P<group_id>[^/]+)/versions/(?P<group_version_id>[^/]+)/?$": response.group_version,
|
"{0}/greengrass/groups/(?P<group_id>[^/]+)/versions/(?P<group_version_id>[^/]+)/?$": response.group_version,
|
||||||
}
|
}
|
||||||
|
@ -473,3 +473,88 @@ def test_get_group_version_with_invalid_version_id():
|
|||||||
f"Version {invalid_group_ver_id} of Group Definition {group_id} does not exist."
|
f"Version {invalid_group_ver_id} of Group Definition {group_id} does not exist."
|
||||||
)
|
)
|
||||||
ex.value.response["Error"]["Code"].should.equal("VersionNotFoundException")
|
ex.value.response["Error"]["Code"].should.equal("VersionNotFoundException")
|
||||||
|
|
||||||
|
|
||||||
|
@freezegun.freeze_time("2022-06-01 12:00:00")
|
||||||
|
@mock_greengrass
|
||||||
|
def test_associate_role_to_group():
|
||||||
|
|
||||||
|
client = boto3.client("greengrass", region_name="ap-northeast-1")
|
||||||
|
res = client.associate_role_to_group(
|
||||||
|
GroupId="abc002c8-1093-485e-9324-3baadf38e582",
|
||||||
|
RoleArn=f"arn:aws:iam::{ACCOUNT_ID}:role/greengrass-role",
|
||||||
|
)
|
||||||
|
|
||||||
|
res.should.have.key("AssociatedAt")
|
||||||
|
res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
|
|
||||||
|
|
||||||
|
@freezegun.freeze_time("2022-06-01 12:00:00")
|
||||||
|
@mock_greengrass
|
||||||
|
def test_get_associated_role():
|
||||||
|
|
||||||
|
client = boto3.client("greengrass", region_name="ap-northeast-1")
|
||||||
|
group_id = "abc002c8-1093-485e-9324-3baadf38e582"
|
||||||
|
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/greengrass-role"
|
||||||
|
client.associate_role_to_group(GroupId=group_id, RoleArn=role_arn)
|
||||||
|
|
||||||
|
res = client.get_associated_role(GroupId=group_id)
|
||||||
|
res.should.have.key("AssociatedAt")
|
||||||
|
res.should.have.key("RoleArn").should.equal(role_arn)
|
||||||
|
res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
|
|
||||||
|
if not TEST_SERVER_MODE:
|
||||||
|
res["AssociatedAt"].should.equal("2022-06-01T12:00:00.000Z")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_greengrass
|
||||||
|
def test_get_associated_role_with_invalid_id():
|
||||||
|
|
||||||
|
client = boto3.client("greengrass", region_name="ap-northeast-1")
|
||||||
|
with pytest.raises(ClientError) as ex:
|
||||||
|
client.get_associated_role(GroupId="abc002c8-1093-485e-9324-3baadf38e582")
|
||||||
|
|
||||||
|
ex.value.response["Error"]["Message"].should.equal(
|
||||||
|
"You need to attach an IAM role to this deployment group."
|
||||||
|
)
|
||||||
|
ex.value.response["Error"]["Code"].should.equal("404")
|
||||||
|
|
||||||
|
|
||||||
|
@freezegun.freeze_time("2022-06-01 12:00:00")
|
||||||
|
@mock_greengrass
|
||||||
|
def test_disassociate_role_from_group():
|
||||||
|
|
||||||
|
client = boto3.client("greengrass", region_name="ap-northeast-1")
|
||||||
|
group_id = "abc002c8-1093-485e-9324-3baadf38e582"
|
||||||
|
role_arn = f"arn:aws:iam::{ACCOUNT_ID}:role/greengrass-role"
|
||||||
|
client.associate_role_to_group(GroupId=group_id, RoleArn=role_arn)
|
||||||
|
client.get_associated_role(GroupId=group_id)
|
||||||
|
|
||||||
|
res = client.disassociate_role_from_group(GroupId=group_id)
|
||||||
|
res.should.have.key("DisassociatedAt")
|
||||||
|
res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
|
|
||||||
|
if not TEST_SERVER_MODE:
|
||||||
|
res["DisassociatedAt"].should.equal("2022-06-01T12:00:00.000Z")
|
||||||
|
|
||||||
|
with pytest.raises(ClientError) as ex:
|
||||||
|
client.get_associated_role(GroupId=group_id)
|
||||||
|
|
||||||
|
ex.value.response["Error"]["Message"].should.equal(
|
||||||
|
"You need to attach an IAM role to this deployment group."
|
||||||
|
)
|
||||||
|
ex.value.response["Error"]["Code"].should.equal("404")
|
||||||
|
|
||||||
|
|
||||||
|
@freezegun.freeze_time("2022-06-01 12:00:00")
|
||||||
|
@mock_greengrass
|
||||||
|
def test_disassociate_role_from_group_with_none_exists_group_id():
|
||||||
|
|
||||||
|
client = boto3.client("greengrass", region_name="ap-northeast-1")
|
||||||
|
group_id = "abc002c8-1093-485e-9324-3baadf38e582"
|
||||||
|
res = client.disassociate_role_from_group(GroupId=group_id)
|
||||||
|
res.should.have.key("DisassociatedAt")
|
||||||
|
res["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||||
|
|
||||||
|
if not TEST_SERVER_MODE:
|
||||||
|
res["DisassociatedAt"].should.equal("2022-06-01T12:00:00.000Z")
|
||||||
|
Loading…
Reference in New Issue
Block a user