boto3-assist 0.11.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/PKG-INFO +1 -1
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/pyproject.toml +5 -1
- boto3_assist-0.13.0/src/boto3_assist/boto3session.py +87 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/connection.py +3 -1
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb.py +2 -4
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_connection.py +2 -0
- boto3_assist-0.13.0/src/boto3_assist/role_assumption_mixin.py +38 -0
- boto3_assist-0.13.0/src/boto3_assist/session_setup_mixin.py +29 -0
- boto3_assist-0.13.0/src/boto3_assist/version.py +1 -0
- boto3_assist-0.13.0/tests/integration/cross_account_connection_test.py +78 -0
- boto3_assist-0.13.0/tests/integration/tenant.py +185 -0
- boto3_assist-0.13.0/tests/integration/tenant_services.py +48 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/cms/content_block.py +1 -1
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/cms/page.py +1 -1
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/cms/template.py +1 -1
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dynamodb_model_base_test.py +1 -1
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dynamodb_model_projections_test.py +2 -2
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dynamodb_model_serializtion_test.py +2 -2
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dynamodb_moto_sorting_test.py +1 -1
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/models_tests/serializable_model_person_test.py +1 -3
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/models_tests/serializable_model_user_test.py +1 -1
- boto3_assist-0.11.0/src/boto3_assist/boto3session.py +0 -180
- boto3_assist-0.11.0/src/boto3_assist/version.py +0 -1
- boto3_assist-0.11.0/tests/__top/__init__.py +0 -25
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.env.docker +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.env.docker.001 +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.env.docker.nosql.workbench +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.env.unittest +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.gitignore +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.vscode/launch.json +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.vscode/settings.json +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/.vscode/tasks.json +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/LICENSE-EXPLAINED.txt +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/LICENSE.txt +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/README.md +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/aws_regions_with_status.csv +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/aws_regions_with_status.json +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/devops/build.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/devops/readme.md +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/__init__.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/cloudwatch/log_report.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/models/order_item_model.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/models/order_model.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/models/product_model.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/models/user_model.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/models/user_post_model.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/order_example/main.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/order_example/products.json +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/order_item_service.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/order_service.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/product_service.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/table_service.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/user_post_service.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/user_service.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/user_service_client_example.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/services/user_service_resource_example.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/dynamodb/user_post_example/main.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/examples/ec2/regions_report.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/module-headers.txt +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/mypy.ini +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/requirements-dev.txt +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/requirements.txt +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/run-checks.sh +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/run_unit_tests.sh +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/__init__.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/aws_lambda/event_info.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/aws_lambda/mock_context.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cloudwatch/cloudwatch_connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cloudwatch/cloudwatch_connection_tracker.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cloudwatch/cloudwatch_log_connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cloudwatch/cloudwatch_logs.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cloudwatch/cloudwatch_query.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cognito/cognito_authorizer.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cognito/cognito_connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cognito/cognito_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cognito/jwks_cache.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/cognito/user.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/connection_tracker.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_helpers.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_importer.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_index.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_iservice.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_key.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_model_base.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_model_base_interfaces.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_reindexer.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/readme.md +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/troubleshooting.md +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/ec2/ec2_connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/environment_services/__init__.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/environment_services/environment_loader.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/environment_services/environment_variables.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/errors/custom_exceptions.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/http_status_codes.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/models/serializable_model.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/s3/s3.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/s3/s3_bucket.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/s3/s3_connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/s3/s3_event_data.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/s3/s3_object.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/securityhub/securityhub.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/securityhub/securityhub_connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/ssm/connection.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/ssm/parameter_store/parameter_store.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/datetime_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/dictionary_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/file_operations.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/http_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/logging_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/numbers_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/serialization_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/utilities/string_utility.py +0 -0
- {boto3_assist-0.11.0 → boto3_assist-0.13.0}/tests/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/cms/base.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/simple_model.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/user_model.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/user_required_fields_model.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dynamodb_reindex_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/examples_test/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/examples_test/user_service_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/lambda_tests/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/lambda_tests/event_info_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/models_tests/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/models_tests/models/person.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/models_tests/models/user.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/models_tests/serializable_model_wide_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/parameter_store/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/parameter_store/parameter_store_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/s3/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/s3/files/test.txt +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/s3/s3_event_data_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/s3/s3_file_delete_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/s3/s3_file_upload_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/utilities/__init__.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/utilities/serialization_utility_test.py +0 -0
- {boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/utilities/string_utility_test.py +0 -0
|
@@ -8,10 +8,14 @@ packages = ["src/boto3_assist"]
|
|
|
8
8
|
[tool.pytest.ini_options]
|
|
9
9
|
pythonpath = ["src"]
|
|
10
10
|
testpaths = ["tests"]
|
|
11
|
+
markers = [
|
|
12
|
+
"integration: marks tests as integration (deselect with '-m \"not integration\"')"
|
|
13
|
+
]
|
|
14
|
+
addopts = "-m 'not integration'"
|
|
11
15
|
|
|
12
16
|
[project]
|
|
13
17
|
name = "boto3_assist"
|
|
14
|
-
version = "0.
|
|
18
|
+
version = "0.13.0"
|
|
15
19
|
|
|
16
20
|
authors = [
|
|
17
21
|
{ name="Eric Wilson", email="boto3-assist@geekcafe.com" }
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, List, Any
|
|
8
|
+
import boto3
|
|
9
|
+
from botocore.config import Config
|
|
10
|
+
from .session_setup_mixin import SessionSetupMixin
|
|
11
|
+
from .role_assumption_mixin import RoleAssumptionMixin
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Boto3SessionManager(SessionSetupMixin, RoleAssumptionMixin):
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
service_name: str,
|
|
18
|
+
*,
|
|
19
|
+
aws_profile: Optional[str] = None,
|
|
20
|
+
aws_region: Optional[str] = None,
|
|
21
|
+
assume_role_arn: Optional[str] = None,
|
|
22
|
+
assume_role_chain: Optional[List[str]] = None,
|
|
23
|
+
assume_role_session_name: Optional[str] = None,
|
|
24
|
+
assume_role_duration_seconds: Optional[int] = 3600,
|
|
25
|
+
config: Optional[Config] = None,
|
|
26
|
+
aws_endpoint_url: Optional[str] = None,
|
|
27
|
+
aws_access_key_id: Optional[str] = None,
|
|
28
|
+
aws_secret_access_key: Optional[str] = None,
|
|
29
|
+
aws_session_token: Optional[str] = None,
|
|
30
|
+
):
|
|
31
|
+
self.service_name = service_name
|
|
32
|
+
self.aws_profile = aws_profile
|
|
33
|
+
self.aws_region = aws_region
|
|
34
|
+
self.config = config
|
|
35
|
+
self.endpoint_url = aws_endpoint_url
|
|
36
|
+
self.assume_role_chain = assume_role_chain or (
|
|
37
|
+
[assume_role_arn] if assume_role_arn else []
|
|
38
|
+
)
|
|
39
|
+
self.assume_role_session_name = (
|
|
40
|
+
assume_role_session_name or f"AssumeRoleSessionFor{service_name}"
|
|
41
|
+
)
|
|
42
|
+
self.assume_role_duration_seconds = assume_role_duration_seconds
|
|
43
|
+
self.aws_access_key_id = aws_access_key_id
|
|
44
|
+
self.aws_secret_access_key = aws_secret_access_key
|
|
45
|
+
self.aws_session_token = aws_session_token
|
|
46
|
+
|
|
47
|
+
self.__session: Optional[boto3.Session] = None
|
|
48
|
+
self.__client: Any = None
|
|
49
|
+
self.__resource: Any = None
|
|
50
|
+
|
|
51
|
+
self.__initialize()
|
|
52
|
+
|
|
53
|
+
def __initialize(self):
|
|
54
|
+
base_session = self._create_base_session(
|
|
55
|
+
self.aws_profile,
|
|
56
|
+
self.aws_region,
|
|
57
|
+
self.aws_access_key_id,
|
|
58
|
+
self.aws_secret_access_key,
|
|
59
|
+
self.aws_session_token,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if self.assume_role_chain:
|
|
63
|
+
self.__session = self._assume_roles_in_chain(
|
|
64
|
+
base_session,
|
|
65
|
+
self.assume_role_chain,
|
|
66
|
+
self.assume_role_session_name,
|
|
67
|
+
self.assume_role_duration_seconds,
|
|
68
|
+
self.aws_region,
|
|
69
|
+
)
|
|
70
|
+
else:
|
|
71
|
+
self.__session = base_session
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def client(self) -> Any:
|
|
75
|
+
if not self.__client:
|
|
76
|
+
self.__client = self.__session.client(
|
|
77
|
+
self.service_name, config=self.config, endpoint_url=self.endpoint_url
|
|
78
|
+
)
|
|
79
|
+
return self.__client
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def resource(self) -> Any:
|
|
83
|
+
if not self.__resource:
|
|
84
|
+
self.__resource = self.__session.resource(
|
|
85
|
+
self.service_name, config=self.config, endpoint_url=self.endpoint_url
|
|
86
|
+
)
|
|
87
|
+
return self.__resource
|
|
@@ -30,6 +30,7 @@ class Connection:
|
|
|
30
30
|
aws_access_key_id: Optional[str] = None,
|
|
31
31
|
aws_secret_access_key: Optional[str] = None,
|
|
32
32
|
aws_end_point_url: Optional[str] = None,
|
|
33
|
+
assume_role_arn: Optional[str] = None,
|
|
33
34
|
) -> None:
|
|
34
35
|
self.__aws_profile = aws_profile
|
|
35
36
|
self.__aws_region = aws_region
|
|
@@ -37,7 +38,7 @@ class Connection:
|
|
|
37
38
|
self.__aws_secret_access_key = aws_secret_access_key
|
|
38
39
|
self.end_point_url = aws_end_point_url
|
|
39
40
|
self.__session: Boto3SessionManager | None = None
|
|
40
|
-
|
|
41
|
+
self.__assume_role_arn: Optional[str] = assume_role_arn
|
|
41
42
|
self.__service_name: str | None = service_name
|
|
42
43
|
|
|
43
44
|
if self.__service_name is None:
|
|
@@ -73,6 +74,7 @@ class Connection:
|
|
|
73
74
|
aws_access_key_id=self.aws_access_key_id,
|
|
74
75
|
aws_secret_access_key=self.aws_secret_access_key,
|
|
75
76
|
aws_endpoint_url=self.end_point_url,
|
|
77
|
+
assume_role_arn=self.__assume_role_arn,
|
|
76
78
|
)
|
|
77
79
|
|
|
78
80
|
tracker.add(service_name=self.service_name)
|
|
@@ -24,7 +24,6 @@ from boto3_assist.utilities.string_utility import StringUtility
|
|
|
24
24
|
logger = Logger()
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
|
|
28
27
|
class DynamoDB(DynamoDBConnection):
|
|
29
28
|
"""
|
|
30
29
|
DynamoDB. Wrapper for basic DynamoDB Connection and Actions
|
|
@@ -41,6 +40,7 @@ class DynamoDB(DynamoDBConnection):
|
|
|
41
40
|
aws_end_point_url: Optional[str] = None,
|
|
42
41
|
aws_access_key_id: Optional[str] = None,
|
|
43
42
|
aws_secret_access_key: Optional[str] = None,
|
|
43
|
+
assume_role_arn: Optional[str] = None,
|
|
44
44
|
) -> None:
|
|
45
45
|
super().__init__(
|
|
46
46
|
aws_profile=aws_profile,
|
|
@@ -48,6 +48,7 @@ class DynamoDB(DynamoDBConnection):
|
|
|
48
48
|
aws_end_point_url=aws_end_point_url,
|
|
49
49
|
aws_access_key_id=aws_access_key_id,
|
|
50
50
|
aws_secret_access_key=aws_secret_access_key,
|
|
51
|
+
assume_role_arn=assume_role_arn,
|
|
51
52
|
)
|
|
52
53
|
self.helpers: DynamoDBHelpers = DynamoDBHelpers()
|
|
53
54
|
self.log_dynamodb_item_size = (
|
|
@@ -55,7 +56,6 @@ class DynamoDB(DynamoDBConnection):
|
|
|
55
56
|
)
|
|
56
57
|
logger.setLevel(os.getenv("LOG_LEVEL", "INFO"))
|
|
57
58
|
|
|
58
|
-
|
|
59
59
|
def save(
|
|
60
60
|
self,
|
|
61
61
|
item: dict | DynamoDBModelBase,
|
|
@@ -169,7 +169,6 @@ class DynamoDB(DynamoDBConnection):
|
|
|
169
169
|
call_type: str = "resource",
|
|
170
170
|
) -> Dict[str, Any]: ...
|
|
171
171
|
|
|
172
|
-
|
|
173
172
|
def get(
|
|
174
173
|
self,
|
|
175
174
|
key: Optional[dict] = None,
|
|
@@ -344,7 +343,6 @@ class DynamoDB(DynamoDBConnection):
|
|
|
344
343
|
) -> dict:
|
|
345
344
|
pass
|
|
346
345
|
|
|
347
|
-
|
|
348
346
|
def delete(
|
|
349
347
|
self,
|
|
350
348
|
*,
|
{boto3_assist-0.11.0 → boto3_assist-0.13.0}/src/boto3_assist/dynamodb/dynamodb_connection.py
RENAMED
|
@@ -32,6 +32,7 @@ class DynamoDBConnection(Connection):
|
|
|
32
32
|
aws_end_point_url: Optional[str] = None,
|
|
33
33
|
aws_access_key_id: Optional[str] = None,
|
|
34
34
|
aws_secret_access_key: Optional[str] = None,
|
|
35
|
+
assume_role_arn: Optional[str] = None,
|
|
35
36
|
) -> None:
|
|
36
37
|
super().__init__(
|
|
37
38
|
service_name="dynamodb",
|
|
@@ -40,6 +41,7 @@ class DynamoDBConnection(Connection):
|
|
|
40
41
|
aws_access_key_id=aws_access_key_id,
|
|
41
42
|
aws_secret_access_key=aws_secret_access_key,
|
|
42
43
|
aws_end_point_url=aws_end_point_url,
|
|
44
|
+
assume_role_arn=assume_role_arn,
|
|
43
45
|
)
|
|
44
46
|
|
|
45
47
|
self.__dynamodb_client: DynamoDBClient | None = None
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import boto3
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RoleAssumptionMixin:
|
|
12
|
+
def _assume_roles_in_chain(
|
|
13
|
+
self,
|
|
14
|
+
base_session: boto3.Session,
|
|
15
|
+
role_chain: List[str],
|
|
16
|
+
session_name: str,
|
|
17
|
+
duration_seconds: int,
|
|
18
|
+
region: str,
|
|
19
|
+
) -> boto3.Session:
|
|
20
|
+
session = base_session
|
|
21
|
+
|
|
22
|
+
for role_arn in role_chain:
|
|
23
|
+
sts_client = session.client("sts")
|
|
24
|
+
response = sts_client.assume_role(
|
|
25
|
+
RoleArn=role_arn,
|
|
26
|
+
RoleSessionName=session_name,
|
|
27
|
+
DurationSeconds=duration_seconds,
|
|
28
|
+
)
|
|
29
|
+
creds = response["Credentials"]
|
|
30
|
+
|
|
31
|
+
session = boto3.Session(
|
|
32
|
+
aws_access_key_id=creds["AccessKeyId"],
|
|
33
|
+
aws_secret_access_key=creds["SecretAccessKey"],
|
|
34
|
+
aws_session_token=creds["SessionToken"],
|
|
35
|
+
region_name=region,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return session
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import boto3
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SessionSetupMixin:
|
|
12
|
+
def _create_base_session(
|
|
13
|
+
self,
|
|
14
|
+
aws_profile: Optional[str],
|
|
15
|
+
aws_region: Optional[str],
|
|
16
|
+
aws_access_key_id: Optional[str],
|
|
17
|
+
aws_secret_access_key: Optional[str],
|
|
18
|
+
aws_session_token: Optional[str],
|
|
19
|
+
) -> boto3.Session:
|
|
20
|
+
try:
|
|
21
|
+
return boto3.Session(
|
|
22
|
+
profile_name=aws_profile,
|
|
23
|
+
region_name=aws_region,
|
|
24
|
+
aws_access_key_id=aws_access_key_id,
|
|
25
|
+
aws_secret_access_key=aws_secret_access_key,
|
|
26
|
+
aws_session_token=aws_session_token,
|
|
27
|
+
)
|
|
28
|
+
except Exception as e:
|
|
29
|
+
raise RuntimeError(f"Failed to create boto3 session: {e}") from e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.13.0'
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import os
|
|
3
|
+
from typing import List
|
|
4
|
+
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
5
|
+
from tests.integration.tenant_services import TenantServices
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.mark.integration
|
|
9
|
+
def test_cross_account_role_assumption_with_profile():
|
|
10
|
+
responses = []
|
|
11
|
+
|
|
12
|
+
profile_name = os.getenv("AWS_PROFILE")
|
|
13
|
+
|
|
14
|
+
connections: List[dict] = [
|
|
15
|
+
{
|
|
16
|
+
"profile_name": profile_name,
|
|
17
|
+
"aws_account": "959096737760",
|
|
18
|
+
"aws_region": "us-east-1",
|
|
19
|
+
"role_name": "CrossAccountAccessRole",
|
|
20
|
+
"table_name": "db-us-east-1",
|
|
21
|
+
"enabled": False,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"profile_name": profile_name,
|
|
25
|
+
"aws_account": "959096737760",
|
|
26
|
+
"aws_region": "eu-west-2",
|
|
27
|
+
"role_name": "CrossAccountAccessRole",
|
|
28
|
+
"table_name": "db-eu-west-2",
|
|
29
|
+
"enabled": False,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"profile_name": profile_name,
|
|
33
|
+
"aws_account": "257932641017",
|
|
34
|
+
"aws_region": "us-east-1",
|
|
35
|
+
"role_name": "CrossAccountAccessRole",
|
|
36
|
+
"table_name": "aplos-nca-saas-production-demo-001-database",
|
|
37
|
+
"enabled": True,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"profile_name": profile_name,
|
|
41
|
+
"aws_region": "us-east-1",
|
|
42
|
+
"aws_account": "211125601483",
|
|
43
|
+
"role_name": "CrossAccountAccessRole",
|
|
44
|
+
"table_name": "aplos-nca-saas-production-app-database",
|
|
45
|
+
"enabled": True,
|
|
46
|
+
},
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
for connection in connections:
|
|
50
|
+
role_arn = (
|
|
51
|
+
f"arn:aws:iam::{connection['aws_account']}:role/{connection['role_name']}"
|
|
52
|
+
)
|
|
53
|
+
if connection["enabled"]:
|
|
54
|
+
db = DynamoDB(
|
|
55
|
+
aws_profile=connection["profile_name"],
|
|
56
|
+
aws_region=connection["aws_region"],
|
|
57
|
+
assume_role_arn=role_arn,
|
|
58
|
+
)
|
|
59
|
+
ts: TenantServices = TenantServices(
|
|
60
|
+
db=db, table_name=connection["table_name"]
|
|
61
|
+
)
|
|
62
|
+
response = ts.list()
|
|
63
|
+
responses.append(response)
|
|
64
|
+
# print(response)
|
|
65
|
+
else:
|
|
66
|
+
responses.append(None)
|
|
67
|
+
|
|
68
|
+
print(len(responses))
|
|
69
|
+
assert len(responses) == 3
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main():
|
|
73
|
+
test_cross_account_role_assumption_with_profile()
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if __name__ == "__main__":
|
|
78
|
+
main()
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tenant Model
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import datetime
|
|
6
|
+
from typing import Optional, Literal
|
|
7
|
+
from boto3_assist.dynamodb.dynamodb_index import (
|
|
8
|
+
DynamoDBIndex,
|
|
9
|
+
DynamoDBKey,
|
|
10
|
+
)
|
|
11
|
+
from boto3_assist.dynamodb.dynamodb_model_base import (
|
|
12
|
+
DynamoDBModelBase,
|
|
13
|
+
exclude_from_serialization,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from boto3_assist.utilities.datetime_utility import DatetimeUtility
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Tenant(DynamoDBModelBase):
|
|
20
|
+
"""Database Model for the Tenant Entity"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
id: Optional[str] = None, # pylint: disable=w0622
|
|
25
|
+
) -> None:
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.id: Optional[str] = id
|
|
28
|
+
self.name: Optional[str] = None
|
|
29
|
+
self.email: Optional[str] = None
|
|
30
|
+
self.subscription_id: Optional[str] = None
|
|
31
|
+
self.type: Optional[str] = None
|
|
32
|
+
self.__status: Optional[str] = None
|
|
33
|
+
self.status_message: str = ""
|
|
34
|
+
self.company_name: Optional[str] = None
|
|
35
|
+
self.created_utc: datetime.datetime = DatetimeUtility.get_utc_now()
|
|
36
|
+
self.modified_utc: datetime.datetime = DatetimeUtility.get_utc_now()
|
|
37
|
+
self.reindexed_utc: Optional[datetime.datetime] = None
|
|
38
|
+
self.__onboard_utc: Optional[datetime.datetime] = None
|
|
39
|
+
self.__setup_indexes()
|
|
40
|
+
|
|
41
|
+
def __setup_indexes(self):
|
|
42
|
+
self.indexes.add_primary(
|
|
43
|
+
DynamoDBIndex(
|
|
44
|
+
index_name="primary",
|
|
45
|
+
partition_key=DynamoDBKey(
|
|
46
|
+
attribute_name="pk",
|
|
47
|
+
value=lambda: f"tenant#{self.id if self.id else ''}",
|
|
48
|
+
),
|
|
49
|
+
sort_key=DynamoDBKey(
|
|
50
|
+
attribute_name="sk",
|
|
51
|
+
value=lambda: f"tenant#{self.id if self.id else ''}",
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
self.indexes.add_secondary(
|
|
57
|
+
DynamoDBIndex(
|
|
58
|
+
index_name="gsi0",
|
|
59
|
+
partition_key=DynamoDBKey(
|
|
60
|
+
attribute_name="gsi0_pk",
|
|
61
|
+
value="tenants#",
|
|
62
|
+
),
|
|
63
|
+
sort_key=DynamoDBKey(
|
|
64
|
+
attribute_name="gsi0_sk",
|
|
65
|
+
value=lambda: f"name#{self.__sort_name if self.__sort_name else ''}",
|
|
66
|
+
),
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
self.indexes.add_secondary(
|
|
71
|
+
DynamoDBIndex(
|
|
72
|
+
index_name="gsi1",
|
|
73
|
+
partition_key=DynamoDBKey(
|
|
74
|
+
attribute_name="gsi1_pk",
|
|
75
|
+
value="tenants#",
|
|
76
|
+
),
|
|
77
|
+
sort_key=DynamoDBKey(
|
|
78
|
+
attribute_name="gsi1_sk",
|
|
79
|
+
value=lambda: (
|
|
80
|
+
f"status#{self.status if self.status else ''}"
|
|
81
|
+
f"name#{self.__sort_name if self.__sort_name else ''}"
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
self.indexes.add_secondary(
|
|
88
|
+
DynamoDBIndex(
|
|
89
|
+
index_name="gsi2",
|
|
90
|
+
partition_key=DynamoDBKey(
|
|
91
|
+
attribute_name="gsi2_pk",
|
|
92
|
+
value="tenants#",
|
|
93
|
+
),
|
|
94
|
+
sort_key=DynamoDBKey(
|
|
95
|
+
attribute_name="gsi2_sk",
|
|
96
|
+
value=lambda: f"onboard-ts#{self.onboard_utc.timestamp() if self.onboard_utc else ''}",
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
@exclude_from_serialization
|
|
103
|
+
def modifed_date(self) -> Optional[str]:
|
|
104
|
+
"""Backward compatibale db model for modified date"""
|
|
105
|
+
return str(self.modified_utc)
|
|
106
|
+
|
|
107
|
+
@modifed_date.setter
|
|
108
|
+
def modifed_date(self, value: Optional[str]) -> None:
|
|
109
|
+
v = DatetimeUtility.to_datetime_utc(value=value)
|
|
110
|
+
|
|
111
|
+
self.modified_utc = v or DatetimeUtility.get_utc_now()
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
@exclude_from_serialization
|
|
115
|
+
def onboarding_date(self) -> Optional[str]:
|
|
116
|
+
"""Backward compatibale db model for modified date"""
|
|
117
|
+
return str(self.onboard_utc)
|
|
118
|
+
|
|
119
|
+
@onboarding_date.setter
|
|
120
|
+
def onboarding_date(self, value: Optional[str]) -> None:
|
|
121
|
+
self.onboard_utc = DatetimeUtility.to_datetime_utc(value=value)
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
@exclude_from_serialization
|
|
125
|
+
def email_address(self) -> Optional[str]:
|
|
126
|
+
"""Backward compatibale db model for email address"""
|
|
127
|
+
return self.email
|
|
128
|
+
|
|
129
|
+
@email_address.setter
|
|
130
|
+
def email_address(self, value: Optional[str]) -> None:
|
|
131
|
+
self.email = value
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def onboard_utc(self) -> Optional[datetime.datetime]:
|
|
135
|
+
"""The UTC date and time the user was onboarded"""
|
|
136
|
+
return DatetimeUtility.to_datetime_utc(self.__onboard_utc)
|
|
137
|
+
|
|
138
|
+
@onboard_utc.setter
|
|
139
|
+
def onboard_utc(self, value: Optional[datetime.datetime]) -> None:
|
|
140
|
+
self.__onboard_utc = DatetimeUtility.to_datetime_utc(
|
|
141
|
+
value=value, default=DatetimeUtility.get_utc_now()
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def status(self) -> Optional[Literal["enabled", "disabled", "locked"]]:
|
|
146
|
+
"""The status of the tenant"""
|
|
147
|
+
|
|
148
|
+
return self.__status
|
|
149
|
+
|
|
150
|
+
@status.setter
|
|
151
|
+
def status(self, value: Optional[Literal["enabled", "disabled", "locked"]]) -> None:
|
|
152
|
+
if value is not None:
|
|
153
|
+
value = str(value).lower()
|
|
154
|
+
|
|
155
|
+
self.__status = value
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def __sort_name(self) -> Optional[str]:
|
|
159
|
+
if self.name is None:
|
|
160
|
+
return None
|
|
161
|
+
else:
|
|
162
|
+
return self.name.lower()
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def record_type(self) -> str:
|
|
166
|
+
"""
|
|
167
|
+
The type of record we are storing to help load the
|
|
168
|
+
correct object at runtime if needed.
|
|
169
|
+
"""
|
|
170
|
+
name = __name__.rsplit(".", maxsplit=1)[-1]
|
|
171
|
+
return name
|
|
172
|
+
|
|
173
|
+
@record_type.setter
|
|
174
|
+
def record_type(self, value: str) -> None:
|
|
175
|
+
pass
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def subscription(self) -> dict | None:
|
|
179
|
+
"""The tenants current subscription - if bound to one"""
|
|
180
|
+
return self.__subscription
|
|
181
|
+
|
|
182
|
+
@subscription.setter
|
|
183
|
+
def subscription(self, value: dict) -> None:
|
|
184
|
+
|
|
185
|
+
self.__subscription = value
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from .tenant import Tenant
|
|
3
|
+
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TenantServices:
|
|
7
|
+
|
|
8
|
+
def __init__(self, db: DynamoDB, table_name: str) -> None:
|
|
9
|
+
self.db: DynamoDB = db or DynamoDB()
|
|
10
|
+
self.table_name: str = table_name
|
|
11
|
+
|
|
12
|
+
def list(
|
|
13
|
+
self,
|
|
14
|
+
*,
|
|
15
|
+
status: Optional[str] = None,
|
|
16
|
+
ascending: bool = True,
|
|
17
|
+
do_projections: bool = False,
|
|
18
|
+
strongly_consistent: bool = False,
|
|
19
|
+
start_key: Optional[dict] = None,
|
|
20
|
+
) -> dict:
|
|
21
|
+
"""
|
|
22
|
+
List all Tenants within an optional status (enabled or )
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
start_key (Optional[str]): A start key for paged results.
|
|
26
|
+
do_projections (bool, optional): Determines if we do projections or not. Defaults to False.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
dict: DynamoDB response dictionary
|
|
30
|
+
"""
|
|
31
|
+
model: Tenant = Tenant()
|
|
32
|
+
index_name: str = "gsi0"
|
|
33
|
+
if status:
|
|
34
|
+
model.status = status
|
|
35
|
+
index_name = "gsi1"
|
|
36
|
+
key = model.get_key(index_name).key()
|
|
37
|
+
response = self.db.query_by_criteria(
|
|
38
|
+
model=model,
|
|
39
|
+
index_name=index_name,
|
|
40
|
+
key=key,
|
|
41
|
+
start_key=start_key,
|
|
42
|
+
do_projections=do_projections,
|
|
43
|
+
table_name=self.table_name,
|
|
44
|
+
strongly_consistent=strongly_consistent,
|
|
45
|
+
ascending=ascending,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return response
|
|
@@ -7,7 +7,7 @@ MIT License. See Project Root for the license information.
|
|
|
7
7
|
import datetime as dt
|
|
8
8
|
from boto3_assist.dynamodb.dynamodb_index import DynamoDBIndex, DynamoDBKey
|
|
9
9
|
from boto3_assist.utilities.string_utility import StringUtility
|
|
10
|
-
from tests.dynamodb_tests.models.cms.base import BaseCMSDBModel
|
|
10
|
+
from tests.unit.dynamodb_tests.models.cms.base import BaseCMSDBModel
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class ContentBlock(BaseCMSDBModel):
|
{boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/cms/page.py
RENAMED
|
@@ -7,7 +7,7 @@ MIT License. See Project Root for the license information.
|
|
|
7
7
|
from typing import List, Dict, Any
|
|
8
8
|
import datetime as dt
|
|
9
9
|
from boto3_assist.dynamodb.dynamodb_index import DynamoDBIndex, DynamoDBKey
|
|
10
|
-
from tests.dynamodb_tests.dbmodels.cms.base import BaseCMSDBModel
|
|
10
|
+
from tests.unit.dynamodb_tests.dbmodels.cms.base import BaseCMSDBModel
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class Page(BaseCMSDBModel):
|
{boto3_assist-0.11.0/tests → boto3_assist-0.13.0/tests/unit}/dynamodb_tests/dbmodels/cms/template.py
RENAMED
|
@@ -6,7 +6,7 @@ MIT License. See Project Root for the license information.
|
|
|
6
6
|
|
|
7
7
|
from typing import List
|
|
8
8
|
from boto3_assist.dynamodb.dynamodb_index import DynamoDBIndex, DynamoDBKey
|
|
9
|
-
from tests.dynamodb_tests.
|
|
9
|
+
from tests.unit.dynamodb_tests.dbmodels.cms.base import BaseCMSDBModel
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class Template(BaseCMSDBModel):
|
|
@@ -9,7 +9,7 @@ from typing import Dict, List
|
|
|
9
9
|
|
|
10
10
|
from boto3_assist.dynamodb.dynamodb_index import DynamoDBIndex
|
|
11
11
|
from boto3_assist.dynamodb.dynamodb_key import DynamoDBKey
|
|
12
|
-
from tests.dynamodb_tests.dbmodels.user_model import User
|
|
12
|
+
from tests.unit.dynamodb_tests.dbmodels.user_model import User
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class DynamoDBModelUnitTest(unittest.TestCase):
|
|
@@ -7,8 +7,8 @@ MIT License. See Project Root for the license information.
|
|
|
7
7
|
import unittest
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
from tests.dynamodb_tests.dbmodels.user_model import User
|
|
11
|
-
from tests.dynamodb_tests.dbmodels.simple_model import Simple
|
|
10
|
+
from tests.unit.dynamodb_tests.dbmodels.user_model import User
|
|
11
|
+
from tests.unit.dynamodb_tests.dbmodels.simple_model import Simple
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class DynamoDBModeProjectionlUnitTest(unittest.TestCase):
|
|
@@ -7,8 +7,8 @@ MIT License. See Project Root for the license information.
|
|
|
7
7
|
import unittest
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
from tests.dynamodb_tests.dbmodels.user_model import User
|
|
11
|
-
from tests.dynamodb_tests.dbmodels.user_required_fields_model import User as User2
|
|
10
|
+
from tests.unit.dynamodb_tests.dbmodels.user_model import User
|
|
11
|
+
from tests.unit.dynamodb_tests.dbmodels.user_required_fields_model import User as User2
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class DynamoDBModelSerializationUnitTest(unittest.TestCase):
|
|
@@ -12,7 +12,7 @@ from mypy_boto3_dynamodb import DynamoDBClient
|
|
|
12
12
|
|
|
13
13
|
from boto3_assist.dynamodb.dynamodb import DynamoDB
|
|
14
14
|
from boto3_assist.environment_services.environment_loader import EnvironmentLoader
|
|
15
|
-
from tests.dynamodb_tests.dbmodels.cms.page import Page
|
|
15
|
+
from tests.unit.dynamodb_tests.dbmodels.cms.page import Page
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
@moto.mock_aws
|
|
@@ -7,9 +7,7 @@ MIT License. See Project Root for the license information.
|
|
|
7
7
|
import unittest
|
|
8
8
|
from typing import Dict, List
|
|
9
9
|
from boto3_assist.models.serializable_model import SerializableModel
|
|
10
|
-
from tests.models_tests.models.person import Person
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
from tests.unit.models_tests.models.person import Person
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
class TestSerializableModel(unittest.TestCase):
|
|
@@ -7,7 +7,7 @@ MIT License. See Project Root for the license information.
|
|
|
7
7
|
import unittest
|
|
8
8
|
from typing import Dict, List, Any
|
|
9
9
|
from boto3_assist.models.serializable_model import SerializableModel
|
|
10
|
-
from tests.models_tests.models.user import User
|
|
10
|
+
from tests.unit.models_tests.models.user import User
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class TestSerializableModel(unittest.TestCase):
|