diff --git a/moto/__init__.py b/moto/__init__.py index da9810f4798a..9f38cba5ec08 100644 --- a/moto/__init__.py +++ b/moto/__init__.py @@ -167,6 +167,7 @@ def f(*args, **kwargs): mock_xray_client = lazy_load(".xray", "mock_xray_client") mock_wafv2 = lazy_load(".wafv2", "mock_wafv2") mock_textract = lazy_load(".textract", "mock_textract") +mock_identitystore = lazy_load(".identitystore", "mock_identitystore") class MockAll(ContextDecorator): diff --git a/moto/backend_index.py b/moto/backend_index.py index 1d19b61840e9..7e2831c35311 100644 --- a/moto/backend_index.py +++ b/moto/backend_index.py @@ -1,4 +1,4 @@ -# autogenerated by scripts/update_backend_index.py +# autogenerated by /Users/danaronson/GitHub/forks/moto/scripts/update_backend_index.py import re backend_url_patterns = [ @@ -79,10 +79,13 @@ ("greengrass", re.compile("https?://greengrass\\.(.+)\\.amazonaws.com")), ("guardduty", re.compile("https?://guardduty\\.(.+)\\.amazonaws\\.com")), ("iam", re.compile("https?://iam\\.(.*\\.)?amazonaws\\.com")), + ("identitystore", re.compile("https?://identitystore\\.(.+)\\.amazonaws\\.com")), ("iot", re.compile("https?://iot\\.(.+)\\.amazonaws\\.com")), ("iot-data", re.compile("https?://data\\.iot\\.(.+)\\.amazonaws.com")), ("iot-data", re.compile("https?://data-ats\\.iot\\.(.+)\\.amazonaws.com")), ("kinesis", re.compile("https?://kinesis\\.(.+)\\.amazonaws\\.com")), + ("kinesis", re.compile("https?://(.+)\\.control-kinesis\\.(.+)\\.amazonaws\\.com")), + ("kinesis", re.compile("https?://(.+)\\.data-kinesis\\.(.+)\\.amazonaws\\.com")), ("kinesisvideo", re.compile("https?://kinesisvideo\\.(.+)\\.amazonaws.com")), ( "kinesis-video-archived-media", diff --git a/moto/identitystore/__init__.py b/moto/identitystore/__init__.py new file mode 100644 index 000000000000..072589539073 --- /dev/null +++ b/moto/identitystore/__init__.py @@ -0,0 +1,5 @@ +"""identitystore module initialization; sets value for base decorator.""" +from .models import identitystore_backends +from ..core.models import base_decorator + +mock_identitystore = base_decorator(identitystore_backends) diff --git a/moto/identitystore/exceptions.py b/moto/identitystore/exceptions.py new file mode 100644 index 000000000000..65060b557388 --- /dev/null +++ b/moto/identitystore/exceptions.py @@ -0,0 +1 @@ +"""Exceptions raised by the identitystore service.""" diff --git a/moto/identitystore/models.py b/moto/identitystore/models.py new file mode 100644 index 000000000000..287610f2182b --- /dev/null +++ b/moto/identitystore/models.py @@ -0,0 +1,28 @@ +"""IdentityStoreBackend class with methods for supported APIs.""" +from moto.moto_api._internal import mock_random + +from moto.core import BaseBackend, BackendDict + + +class IdentityStoreBackend(BaseBackend): + """Implementation of IdentityStore APIs.""" + + def __init__(self, region_name, account_id): + super().__init__(region_name, account_id) + self.groups = {} + + # add methods from here + + def create_group(self, identity_store_id, display_name, description): + group_id = str(mock_random.uuid4()) + group_dict = { + "GroupId": group_id, + "IdentityStoreId": identity_store_id, + "DisplayName": display_name, + "Description": description, + } + self.groups[group_id] = group_dict + return group_id, identity_store_id + + +identitystore_backends = BackendDict(IdentityStoreBackend, "identitystore") diff --git a/moto/identitystore/responses.py b/moto/identitystore/responses.py new file mode 100644 index 000000000000..0308631a2c94 --- /dev/null +++ b/moto/identitystore/responses.py @@ -0,0 +1,34 @@ +"""Handles incoming identitystore requests, invokes methods, returns responses.""" +import json + +from moto.core.responses import BaseResponse +from .models import identitystore_backends + + +class IdentityStoreResponse(BaseResponse): + """Handler for IdentityStore requests and responses.""" + + def __init__(self): + super().__init__(service_name="identitystore") + + @property + def identitystore_backend(self): + """Return backend instance specific for this region.""" + return identitystore_backends[self.current_account][self.region] + + # add methods from here + + def create_group(self): + params = self._get_params() + identity_store_id = params.get("IdentityStoreId") + display_name = params.get("DisplayName") + description = params.get("Description") + group_id, identity_store_id = self.identitystore_backend.create_group( + identity_store_id=identity_store_id, + display_name=display_name, + description=description, + ) + return json.dumps(dict(GroupId=group_id, IdentityStoreId=identity_store_id)) + + def _get_params(self): + return json.loads(self.body) diff --git a/moto/identitystore/urls.py b/moto/identitystore/urls.py new file mode 100644 index 000000000000..11696e6dd31a --- /dev/null +++ b/moto/identitystore/urls.py @@ -0,0 +1,10 @@ +"""identitystore base URL and path.""" +from .responses import IdentityStoreResponse + +url_bases = [ + r"https?://identitystore\.(.+)\.amazonaws\.com", +] + +url_paths = { + "{0}/$": IdentityStoreResponse.dispatch, +} diff --git a/tests/test_identitystore/__init__.py b/tests/test_identitystore/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/test_identitystore/test_identitystore.py b/tests/test_identitystore/test_identitystore.py new file mode 100644 index 000000000000..440889e06dd1 --- /dev/null +++ b/tests/test_identitystore/test_identitystore.py @@ -0,0 +1,24 @@ +"""Unit tests for identitystore-supported APIs.""" +from uuid import UUID + +import boto3 +import sure # noqa # pylint: disable=unused-import + +from moto import mock_identitystore + + +# See our Development Tips on writing tests for hints on how to write good tests: +# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html + + +@mock_identitystore +def test_create_group(): + client = boto3.client("identitystore", region_name="ap-southeast-1") + identity_store_id = "d-9067028cf5" + create_resp = client.create_group( + IdentityStoreId=identity_store_id, + DisplayName="test_group", + Description="description", + ) + assert create_resp["IdentityStoreId"] == identity_store_id + assert UUID(create_resp["GroupId"])