diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md index 4a5561038..b113eddf4 100644 --- a/IMPLEMENTATION_COVERAGE.md +++ b/IMPLEMENTATION_COVERAGE.md @@ -4040,6 +4040,127 @@ - [ ] synthesize_speech +## quicksight +
+6% implemented + +- [ ] cancel_ingestion +- [ ] create_account_customization +- [ ] create_analysis +- [ ] create_dashboard +- [ ] create_data_set +- [ ] create_data_source +- [ ] create_folder +- [ ] create_folder_membership +- [X] create_group +- [ ] create_group_membership +- [ ] create_iam_policy_assignment +- [ ] create_ingestion +- [ ] create_namespace +- [ ] create_template +- [ ] create_template_alias +- [ ] create_theme +- [ ] create_theme_alias +- [ ] delete_account_customization +- [ ] delete_analysis +- [ ] delete_dashboard +- [ ] delete_data_set +- [ ] delete_data_source +- [ ] delete_folder +- [ ] delete_folder_membership +- [X] delete_group +- [ ] delete_group_membership +- [ ] delete_iam_policy_assignment +- [ ] delete_namespace +- [ ] delete_template +- [ ] delete_template_alias +- [ ] delete_theme +- [ ] delete_theme_alias +- [X] delete_user +- [ ] delete_user_by_principal_id +- [ ] describe_account_customization +- [ ] describe_account_settings +- [ ] describe_analysis +- [ ] describe_analysis_permissions +- [ ] describe_dashboard +- [ ] describe_dashboard_permissions +- [ ] describe_data_set +- [ ] describe_data_set_permissions +- [ ] describe_data_source +- [ ] describe_data_source_permissions +- [ ] describe_folder +- [ ] describe_folder_permissions +- [ ] describe_folder_resolved_permissions +- [X] describe_group +- [ ] describe_iam_policy_assignment +- [ ] describe_ingestion +- [ ] describe_ip_restriction +- [ ] describe_namespace +- [ ] describe_template +- [ ] describe_template_alias +- [ ] describe_template_permissions +- [ ] describe_theme +- [ ] describe_theme_alias +- [ ] describe_theme_permissions +- [X] describe_user +- [ ] generate_embed_url_for_anonymous_user +- [ ] generate_embed_url_for_registered_user +- [ ] get_dashboard_embed_url +- [ ] get_session_embed_url +- [ ] list_analyses +- [ ] list_dashboard_versions +- [ ] list_dashboards +- [ ] list_data_sets +- [ ] list_data_sources +- [ ] list_folder_members +- [ ] list_folders +- [ ] list_group_memberships +- [ ] list_groups +- [ ] list_iam_policy_assignments +- [ ] list_iam_policy_assignments_for_user +- [ ] list_ingestions +- [ ] list_namespaces +- [ ] list_tags_for_resource +- [ ] list_template_aliases +- [ ] list_template_versions +- [ ] list_templates +- [ ] list_theme_aliases +- [ ] list_theme_versions +- [ ] list_themes +- [ ] list_user_groups +- [ ] list_users +- [X] register_user +- [ ] restore_analysis +- [ ] search_analyses +- [ ] search_dashboards +- [ ] search_folders +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_account_customization +- [ ] update_account_settings +- [ ] update_analysis +- [ ] update_analysis_permissions +- [ ] update_dashboard +- [ ] update_dashboard_permissions +- [ ] update_dashboard_published_version +- [ ] update_data_set +- [ ] update_data_set_permissions +- [ ] update_data_source +- [ ] update_data_source_permissions +- [ ] update_folder +- [ ] update_folder_permissions +- [X] update_group +- [ ] update_iam_policy_assignment +- [ ] update_ip_restriction +- [ ] update_template +- [ ] update_template_alias +- [ ] update_template_permissions +- [ ] update_theme +- [ ] update_theme_alias +- [ ] update_theme_permissions +- [ ] update_user +
+ ## ram
20% implemented @@ -5762,7 +5883,6 @@ - proton - qldb - qldb-session -- quicksight - rbin - rds-data - rekognition diff --git a/docs/docs/services/quicksight.rst b/docs/docs/services/quicksight.rst new file mode 100644 index 000000000..0732a9043 --- /dev/null +++ b/docs/docs/services/quicksight.rst @@ -0,0 +1,150 @@ +.. _implementedservice_quicksight: + +.. |start-h3| raw:: html + +

+ +.. |end-h3| raw:: html + +

+ +========== +quicksight +========== + +.. autoclass:: moto.quicksight.models.QuickSightBackend + +|start-h3| Example usage |end-h3| + +.. sourcecode:: python + + @mock_quicksight + def test_quicksight_behaviour: + boto3.client("quicksight") + ... + + + +|start-h3| Implemented features for this service |end-h3| + +- [ ] cancel_ingestion +- [ ] create_account_customization +- [ ] create_analysis +- [ ] create_dashboard +- [ ] create_data_set +- [ ] create_data_source +- [ ] create_folder +- [ ] create_folder_membership +- [X] create_group +- [ ] create_group_membership +- [ ] create_iam_policy_assignment +- [ ] create_ingestion +- [ ] create_namespace +- [ ] create_template +- [ ] create_template_alias +- [ ] create_theme +- [ ] create_theme_alias +- [ ] delete_account_customization +- [ ] delete_analysis +- [ ] delete_dashboard +- [ ] delete_data_set +- [ ] delete_data_source +- [ ] delete_folder +- [ ] delete_folder_membership +- [X] delete_group +- [ ] delete_group_membership +- [ ] delete_iam_policy_assignment +- [ ] delete_namespace +- [ ] delete_template +- [ ] delete_template_alias +- [ ] delete_theme +- [ ] delete_theme_alias +- [X] delete_user +- [ ] delete_user_by_principal_id +- [ ] describe_account_customization +- [ ] describe_account_settings +- [ ] describe_analysis +- [ ] describe_analysis_permissions +- [ ] describe_dashboard +- [ ] describe_dashboard_permissions +- [ ] describe_data_set +- [ ] describe_data_set_permissions +- [ ] describe_data_source +- [ ] describe_data_source_permissions +- [ ] describe_folder +- [ ] describe_folder_permissions +- [ ] describe_folder_resolved_permissions +- [X] describe_group +- [ ] describe_iam_policy_assignment +- [ ] describe_ingestion +- [ ] describe_ip_restriction +- [ ] describe_namespace +- [ ] describe_template +- [ ] describe_template_alias +- [ ] describe_template_permissions +- [ ] describe_theme +- [ ] describe_theme_alias +- [ ] describe_theme_permissions +- [X] describe_user +- [ ] generate_embed_url_for_anonymous_user +- [ ] generate_embed_url_for_registered_user +- [ ] get_dashboard_embed_url +- [ ] get_session_embed_url +- [ ] list_analyses +- [ ] list_dashboard_versions +- [ ] list_dashboards +- [ ] list_data_sets +- [ ] list_data_sources +- [ ] list_folder_members +- [ ] list_folders +- [ ] list_group_memberships +- [ ] list_groups +- [ ] list_iam_policy_assignments +- [ ] list_iam_policy_assignments_for_user +- [ ] list_ingestions +- [ ] list_namespaces +- [ ] list_tags_for_resource +- [ ] list_template_aliases +- [ ] list_template_versions +- [ ] list_templates +- [ ] list_theme_aliases +- [ ] list_theme_versions +- [ ] list_themes +- [ ] list_user_groups +- [ ] list_users +- [X] register_user + + The following parameters are not yet implemented: + IamArn, SessionName, CustomsPermissionsName, ExternalLoginFederationProviderType, CustomFederationProviderUrl, ExternalLoginId + + +- [ ] restore_analysis +- [ ] search_analyses +- [ ] search_dashboards +- [ ] search_folders +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_account_customization +- [ ] update_account_settings +- [ ] update_analysis +- [ ] update_analysis_permissions +- [ ] update_dashboard +- [ ] update_dashboard_permissions +- [ ] update_dashboard_published_version +- [ ] update_data_set +- [ ] update_data_set_permissions +- [ ] update_data_source +- [ ] update_data_source_permissions +- [ ] update_folder +- [ ] update_folder_permissions +- [X] update_group +- [ ] update_iam_policy_assignment +- [ ] update_ip_restriction +- [ ] update_template +- [ ] update_template_alias +- [ ] update_template_permissions +- [ ] update_theme +- [ ] update_theme_alias +- [ ] update_theme_permissions +- [ ] update_user + diff --git a/moto/__init__.py b/moto/__init__.py index 92658a359..75796f5da 100644 --- a/moto/__init__.py +++ b/moto/__init__.py @@ -124,6 +124,7 @@ mock_opsworks = lazy_load(".opsworks", "mock_opsworks") mock_organizations = lazy_load(".organizations", "mock_organizations") mock_pinpoint = lazy_load(".pinpoint", "mock_pinpoint") mock_polly = lazy_load(".polly", "mock_polly") +mock_quicksight = lazy_load(".quicksight", "mock_quicksight") mock_ram = lazy_load(".ram", "mock_ram") mock_rds = lazy_load(".rds", "mock_rds") mock_rds2 = lazy_load(".rds", "mock_rds", use_instead=("mock_rds2", "mock_rds")) diff --git a/moto/backend_index.py b/moto/backend_index.py index 167d960f5..64808c91c 100644 --- a/moto/backend_index.py +++ b/moto/backend_index.py @@ -1,4 +1,4 @@ -# autogenerated by ./scripts/update_backend_index.py +# autogenerated by scripts/update_backend_index.py import re backend_url_patterns = [ @@ -32,7 +32,6 @@ backend_url_patterns = [ ("dms", re.compile("https?://dms\\.(.+)\\.amazonaws\\.com")), ("ds", re.compile("https?://ds\\.(.+)\\.amazonaws\\.com")), ("dynamodb", re.compile("https?://dynamodb\\.(.+)\\.amazonaws\\.com")), - ("dynamodb2", re.compile("https?://dynamodb\\.(.+)\\.amazonaws\\.com")), ( "dynamodbstreams", re.compile("https?://streams\\.dynamodb\\.(.+)\\.amazonaws.com"), @@ -97,6 +96,7 @@ backend_url_patterns = [ ("organizations", re.compile("https?://organizations\\.(.+)\\.amazonaws\\.com")), ("pinpoint", re.compile("https?://pinpoint\\.(.+)\\.amazonaws\\.com")), ("polly", re.compile("https?://polly\\.(.+)\\.amazonaws.com")), + ("quicksight", re.compile("https?://quicksight\\.(.+)\\.amazonaws\\.com")), ("ram", re.compile("https?://ram\\.(.+)\\.amazonaws.com")), ("rds", re.compile("https?://rds\\.(.+)\\.amazonaws\\.com")), ("rds", re.compile("https?://rds\\.amazonaws\\.com")), @@ -154,4 +154,5 @@ backend_url_patterns = [ ("transcribe", re.compile("https?://transcribe\\.(.+)\\.amazonaws\\.com")), ("wafv2", re.compile("https?://wafv2\\.(.+)\\.amazonaws.com")), ("xray", re.compile("https?://xray\\.(.+)\\.amazonaws.com")), + ("dynamodb_v20111205", re.compile("https?://dynamodb\\.(.+)\\.amazonaws\\.com")), ] diff --git a/moto/quicksight/__init__.py b/moto/quicksight/__init__.py new file mode 100644 index 000000000..c58340038 --- /dev/null +++ b/moto/quicksight/__init__.py @@ -0,0 +1,5 @@ +"""quicksight module initialization; sets value for base decorator.""" +from .models import quicksight_backends +from ..core.models import base_decorator + +mock_quicksight = base_decorator(quicksight_backends) diff --git a/moto/quicksight/exceptions.py b/moto/quicksight/exceptions.py new file mode 100644 index 000000000..045cf4c7e --- /dev/null +++ b/moto/quicksight/exceptions.py @@ -0,0 +1,7 @@ +"""Exceptions raised by the quicksight service.""" +from moto.core.exceptions import JsonRESTError + + +class ResourceNotFoundException(JsonRESTError): + def __init__(self, msg): + super().__init__("ResourceNotFoundException", msg) diff --git a/moto/quicksight/models.py b/moto/quicksight/models.py new file mode 100644 index 000000000..ce75d8a85 --- /dev/null +++ b/moto/quicksight/models.py @@ -0,0 +1,112 @@ +"""QuickSightBackend class with methods for supported APIs.""" + +from moto.core import ACCOUNT_ID, BaseBackend, BaseModel +from moto.core.utils import BackendDict +from .exceptions import ResourceNotFoundException + + +class QuicksightGroup(BaseModel): + def __init__(self, region, group_name, description, aws_account_id, namespace): + self.arn = ( + f"arn:aws:quicksight:{region}:{ACCOUNT_ID}:group/default/{group_name}" + ) + self.group_name = group_name + self.description = description + self.aws_account_id = aws_account_id + self.namespace = namespace + + def to_json(self): + return { + "Arn": self.arn, + "GroupName": self.group_name, + "Description": self.description, + "PrincipalId": self.aws_account_id, + "Namespace": self.namespace, + } + + +class QuicksightUser(BaseModel): + def __init__(self, region, email, identity_type, username, user_role): + self.arn = f"arn:aws:quicksight:{region}:{ACCOUNT_ID}:user/default/{username}" + self.email = email + self.identity_type = identity_type + self.username = username + self.user_role = user_role + self.active = False + + def to_json(self): + return { + "Arn": self.arn, + "Email": self.email, + "IdentityType": self.identity_type, + "Role": self.user_role, + "UserName": self.username, + "Active": self.active, + } + + +class QuickSightBackend(BaseBackend): + """Implementation of QuickSight APIs.""" + + def __init__(self, region_name=None): + self.region_name = region_name + self.groups = dict() + self.users = dict() + + def reset(self): + """Re-initialize all attributes for this instance.""" + region_name = self.region_name + self.__dict__ = {} + self.__init__(region_name) + + def create_group(self, group_name, description, aws_account_id, namespace): + group = QuicksightGroup( + region=self.region_name, + group_name=group_name, + description=description, + aws_account_id=aws_account_id, + namespace=namespace, + ) + self.groups[f"{aws_account_id}:{namespace}:{group_name}"] = group + return group + + def delete_group(self, aws_account_id, namespace, group_name): + self.groups.pop(f"{aws_account_id}:{namespace}:{group_name}", None) + + def delete_user(self, aws_account_id, namespace, user_name): + self.users.pop(f"{aws_account_id}:{namespace}:{user_name}", None) + + def describe_group(self, aws_account_id, namespace, group_name): + if f"{aws_account_id}:{namespace}:{group_name}" not in self.groups: + raise ResourceNotFoundException(f"Group {group_name} not found") + return self.groups[f"{aws_account_id}:{namespace}:{group_name}"] + + def describe_user(self, aws_account_id, namespace, user_name): + if f"{aws_account_id}:{namespace}:{user_name}" not in self.users: + raise ResourceNotFoundException(f"User {user_name} not found") + return self.users[f"{aws_account_id}:{namespace}:{user_name}"] + + def register_user( + self, identity_type, email, user_role, aws_account_id, namespace, user_name + ): + """ + The following parameters are not yet implemented: + IamArn, SessionName, CustomsPermissionsName, ExternalLoginFederationProviderType, CustomFederationProviderUrl, ExternalLoginId + """ + user = QuicksightUser( + region=self.region_name, + email=email, + identity_type=identity_type, + user_role=user_role, + username=user_name, + ) + self.users[f"{aws_account_id}:{namespace}:{user_name}"] = user + return user + + def update_group(self, aws_account_id, namespace, group_name, description): + group = self.describe_group(aws_account_id, namespace, group_name) + group.description = description + return group + + +quicksight_backends = BackendDict(QuickSightBackend, "quicksight") diff --git a/moto/quicksight/responses.py b/moto/quicksight/responses.py new file mode 100644 index 000000000..69a45f446 --- /dev/null +++ b/moto/quicksight/responses.py @@ -0,0 +1,119 @@ +"""Handles incoming quicksight requests, invokes methods, returns responses.""" +import json + +from moto.core.responses import BaseResponse +from .models import quicksight_backends + + +class QuickSightResponse(BaseResponse): + """Handler for QuickSight requests and responses.""" + + @property + def quicksight_backend(self): + """Return backend instance specific for this region.""" + return quicksight_backends[self.region] + + def groups(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + if request.method == "POST": + return self.create_group() + + def group(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + if request.method == "GET": + return self.describe_group() + if request.method == "DELETE": + return self.delete_group() + if request.method == "PUT": + return self.update_group() + + def users(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + if request.method == "POST": + return self.register_user() + + def user(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + if request.method == "GET": + return self.describe_user() + if request.method == "DELETE": + return self.delete_user() + + def create_group(self): + params = json.loads(self.body) + group_name = params.get("GroupName") + description = params.get("Description") + aws_account_id = self.path.split("/")[-4] + namespace = self.path.split("/")[-2] + group = self.quicksight_backend.create_group( + group_name=group_name, + description=description, + aws_account_id=aws_account_id, + namespace=namespace, + ) + return 200, {}, json.dumps(dict(Group=group.to_json())) + + def register_user(self): + params = json.loads(self.body) + identity_type = params.get("IdentityType") + email = params.get("Email") + user_role = params.get("UserRole") + aws_account_id = self.path.split("/")[-4] + namespace = self.path.split("/")[-2] + user_name = params.get("UserName") + user = self.quicksight_backend.register_user( + identity_type=identity_type, + email=email, + user_role=user_role, + aws_account_id=aws_account_id, + namespace=namespace, + user_name=user_name, + ) + return 200, {}, json.dumps(dict(User=user.to_json(), UserInvitationUrl="TBD")) + + def describe_group(self): + aws_account_id = self.path.split("/")[-5] + namespace = self.path.split("/")[-3] + group_name = self.path.split("/")[-1] + + group = self.quicksight_backend.describe_group( + aws_account_id, namespace, group_name + ) + return 200, {}, json.dumps(dict(Group=group.to_json())) + + def describe_user(self): + aws_account_id = self.path.split("/")[-5] + namespace = self.path.split("/")[-3] + user_name = self.path.split("/")[-1] + + user = self.quicksight_backend.describe_user( + aws_account_id, namespace, user_name + ) + return 200, {}, json.dumps(dict(User=user.to_json())) + + def delete_group(self): + aws_account_id = self.path.split("/")[-5] + namespace = self.path.split("/")[-3] + group_name = self.path.split("/")[-1] + + self.quicksight_backend.delete_group(aws_account_id, namespace, group_name) + return 204, {}, json.dumps({"Status": 204}) + + def delete_user(self): + aws_account_id = self.path.split("/")[-5] + namespace = self.path.split("/")[-3] + user_name = self.path.split("/")[-1] + + self.quicksight_backend.delete_user(aws_account_id, namespace, user_name) + return 204, {}, json.dumps({"Status": 204}) + + def update_group(self): + aws_account_id = self.path.split("/")[-5] + namespace = self.path.split("/")[-3] + group_name = self.path.split("/")[-1] + description = json.loads(self.body).get("Description") + + group = self.quicksight_backend.update_group( + aws_account_id, namespace, group_name, description + ) + return 200, {}, json.dumps(dict(Group=group.to_json())) diff --git a/moto/quicksight/urls.py b/moto/quicksight/urls.py new file mode 100644 index 000000000..872ed93cf --- /dev/null +++ b/moto/quicksight/urls.py @@ -0,0 +1,17 @@ +"""quicksight base URL and path.""" +from .responses import QuickSightResponse + +url_bases = [ + r"https?://quicksight\.(.+)\.amazonaws\.com", +] + + +response = QuickSightResponse() + + +url_paths = { + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[^/.]+)/groups$": response.groups, + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[^/.]+)/groups/(?P[^/.]+)$": response.group, + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[^/.]+)/users$": response.users, + r"{0}/accounts/(?P[\d]+)/namespaces/(?P[^/.]+)/users/(?P[^/.]+)$": response.user, +} diff --git a/tests/terraform-tests.success.txt b/tests/terraform-tests.success.txt index d51728bba..2d6e1be66 100644 --- a/tests/terraform-tests.success.txt +++ b/tests/terraform-tests.success.txt @@ -113,6 +113,8 @@ TestAccAWSPartition TestAccAWSPinpointApp TestAccAWSPinpointEventStream TestAccAWSProvider +TestAccAWSQuickSightGroup +TestAccAWSQuickSightUser TestAccAWSRedshiftServiceAccount TestAccAWSRolePolicyAttachment TestAccAWSRouteTable_ diff --git a/tests/test_quicksight/__init__.py b/tests/test_quicksight/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_quicksight/test_quicksight_groups.py b/tests/test_quicksight/test_quicksight_groups.py new file mode 100644 index 000000000..89bcbeb4c --- /dev/null +++ b/tests/test_quicksight/test_quicksight_groups.py @@ -0,0 +1,108 @@ +"""Unit tests for quicksight-supported APIs.""" +import boto3 +import pytest +import sure # noqa # pylint: disable=unused-import + +from botocore.exceptions import ClientError +from moto import mock_quicksight +from moto.core import ACCOUNT_ID + +# 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_quicksight +def test_create_group(): + client = boto3.client("quicksight", region_name="us-west-2") + resp = client.create_group( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + GroupName="mygroup", + Description="my new fancy group", + ) + + resp.should.have.key("Group") + + resp["Group"].should.have.key("Arn").equals( + f"arn:aws:quicksight:us-west-2:{ACCOUNT_ID}:group/default/mygroup" + ) + resp["Group"].should.have.key("GroupName").equals("mygroup") + resp["Group"].should.have.key("Description").equals("my new fancy group") + resp["Group"].should.have.key("PrincipalId").equals(f"{ACCOUNT_ID}") + + +@mock_quicksight +def test_describe_group(): + client = boto3.client("quicksight", region_name="us-west-2") + client.create_group( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + GroupName="mygroup", + Description="my new fancy group", + ) + + resp = client.describe_group( + GroupName="mygroup", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + + resp.should.have.key("Group") + + resp["Group"].should.have.key("Arn").equals( + f"arn:aws:quicksight:us-west-2:{ACCOUNT_ID}:group/default/mygroup" + ) + resp["Group"].should.have.key("GroupName").equals("mygroup") + resp["Group"].should.have.key("Description").equals("my new fancy group") + resp["Group"].should.have.key("PrincipalId").equals(f"{ACCOUNT_ID}") + + +@mock_quicksight +def test_update_group(): + client = boto3.client("quicksight", region_name="us-west-2") + client.create_group( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + GroupName="mygroup", + Description="desc1", + ) + + resp = client.update_group( + GroupName="mygroup", + AwsAccountId=ACCOUNT_ID, + Namespace="default", + Description="desc2", + ) + resp.should.have.key("Group").should.have.key("Description").equals("desc2") + + resp = client.describe_group( + GroupName="mygroup", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + + resp.should.have.key("Group") + resp["Group"].should.have.key("Arn").equals( + f"arn:aws:quicksight:us-west-2:{ACCOUNT_ID}:group/default/mygroup" + ) + resp["Group"].should.have.key("GroupName").equals("mygroup") + resp["Group"].should.have.key("Description").equals("desc2") + resp["Group"].should.have.key("PrincipalId").equals(f"{ACCOUNT_ID}") + + +@mock_quicksight +def test_delete_group(): + client = boto3.client("quicksight", region_name="us-east-2") + client.create_group( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + GroupName="mygroup", + Description="my new fancy group", + ) + + client.delete_group( + GroupName="mygroup", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + + with pytest.raises(ClientError) as exc: + client.describe_group( + GroupName="mygroup", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + err = exc.value.response["Error"] + err["Code"].should.equal("ResourceNotFoundException") diff --git a/tests/test_quicksight/test_quicksight_users.py b/tests/test_quicksight/test_quicksight_users.py new file mode 100644 index 000000000..238861f53 --- /dev/null +++ b/tests/test_quicksight/test_quicksight_users.py @@ -0,0 +1,88 @@ +"""Unit tests for quicksight-supported APIs.""" +import boto3 +import pytest +import sure # noqa # pylint: disable=unused-import + +from botocore.exceptions import ClientError +from moto import mock_quicksight +from moto.core import ACCOUNT_ID + +# 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_quicksight +def test_register_user__quicksight(): + client = boto3.client("quicksight", region_name="us-east-2") + resp = client.register_user( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + Email="fakeemail@example.com", + IdentityType="QUICKSIGHT", + UserName="tfacctestm9hpsr970z", + UserRole="READER", + ) + + resp.should.have.key("UserInvitationUrl") + resp.should.have.key("User") + + resp["User"].should.have.key("Arn").equals( + f"arn:aws:quicksight:us-east-2:{ACCOUNT_ID}:user/default/tfacctestm9hpsr970z" + ) + resp["User"].should.have.key("UserName").equals("tfacctestm9hpsr970z") + resp["User"].should.have.key("Email").equals("fakeemail@example.com") + resp["User"].should.have.key("Role").equals("READER") + resp["User"].should.have.key("IdentityType").equals("QUICKSIGHT") + resp["User"].should.have.key("Active").equals(False) + + +@mock_quicksight +def test_describe_user__quicksight(): + client = boto3.client("quicksight", region_name="us-east-1") + client.register_user( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + Email="fakeemail@example.com", + IdentityType="QUICKSIGHT", + UserName="tfacctestm9hpsr970z", + UserRole="READER", + ) + + resp = client.describe_user( + UserName="tfacctestm9hpsr970z", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + + resp.should.have.key("User") + + resp["User"].should.have.key("Arn").equals( + f"arn:aws:quicksight:us-east-1:{ACCOUNT_ID}:user/default/tfacctestm9hpsr970z" + ) + resp["User"].should.have.key("UserName").equals("tfacctestm9hpsr970z") + resp["User"].should.have.key("Email").equals("fakeemail@example.com") + resp["User"].should.have.key("Role").equals("READER") + resp["User"].should.have.key("IdentityType").equals("QUICKSIGHT") + resp["User"].should.have.key("Active").equals(False) + + +@mock_quicksight +def test_delete_user__quicksight(): + client = boto3.client("quicksight", region_name="us-east-2") + client.register_user( + AwsAccountId=ACCOUNT_ID, + Namespace="default", + Email="fakeemail@example.com", + IdentityType="QUICKSIGHT", + UserName="tfacctestm9hpsr970z", + UserRole="READER", + ) + + client.delete_user( + UserName="tfacctestm9hpsr970z", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + + with pytest.raises(ClientError) as exc: + client.describe_user( + UserName="tfacctestm9hpsr970z", AwsAccountId=ACCOUNT_ID, Namespace="default" + ) + err = exc.value.response["Error"] + err["Code"].should.equal("ResourceNotFoundException")