clear-skies-aws 1.10.2__py3-none-any.whl → 2.0.2__py3-none-any.whl

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.
Files changed (86) hide show
  1. {clear_skies_aws-1.10.2.dist-info → clear_skies_aws-2.0.2.dist-info}/METADATA +36 -35
  2. clear_skies_aws-2.0.2.dist-info/RECORD +63 -0
  3. {clear_skies_aws-1.10.2.dist-info → clear_skies_aws-2.0.2.dist-info}/WHEEL +1 -1
  4. clear_skies_aws-2.0.2.dist-info/licenses/LICENSE +21 -0
  5. clearskies_aws/__init__.py +15 -2
  6. clearskies_aws/actions/__init__.py +13 -106
  7. clearskies_aws/actions/action_aws.py +74 -57
  8. clearskies_aws/actions/assume_role.py +43 -30
  9. clearskies_aws/actions/ses.py +82 -73
  10. clearskies_aws/actions/sns.py +27 -30
  11. clearskies_aws/actions/sqs.py +32 -33
  12. clearskies_aws/actions/step_function.py +38 -31
  13. clearskies_aws/backends/__init__.py +11 -4
  14. clearskies_aws/backends/backend.py +106 -0
  15. clearskies_aws/backends/dynamo_db_backend.py +150 -155
  16. clearskies_aws/backends/dynamo_db_condition_parser.py +40 -80
  17. clearskies_aws/backends/dynamo_db_parti_ql_backend.py +179 -337
  18. clearskies_aws/backends/sqs_backend.py +32 -51
  19. clearskies_aws/configs/__init__.py +0 -0
  20. clearskies_aws/contexts/__init__.py +23 -10
  21. clearskies_aws/contexts/cli_web_socket_mock.py +19 -0
  22. clearskies_aws/contexts/lambda_alb.py +76 -0
  23. clearskies_aws/contexts/lambda_api_gateway.py +75 -28
  24. clearskies_aws/contexts/lambda_api_gateway_web_socket.py +56 -29
  25. clearskies_aws/contexts/lambda_invocation.py +15 -44
  26. clearskies_aws/contexts/lambda_sns.py +8 -33
  27. clearskies_aws/contexts/lambda_sqs_standard_partial_batch.py +14 -36
  28. clearskies_aws/di/__init__.py +6 -1
  29. clearskies_aws/di/aws_additional_config_auto_import.py +37 -0
  30. clearskies_aws/di/inject/__init__.py +6 -0
  31. clearskies_aws/di/inject/boto3.py +15 -0
  32. clearskies_aws/di/inject/boto3_session.py +13 -0
  33. clearskies_aws/di/inject/parameter_store.py +15 -0
  34. clearskies_aws/{handlers → endpoints}/secrets_manager_rotation.py +76 -55
  35. clearskies_aws/endpoints/simple_body_routing.py +41 -0
  36. clearskies_aws/input_outputs/__init__.py +21 -8
  37. clearskies_aws/input_outputs/{cli_websocket_mock.py → cli_web_socket_mock.py} +9 -3
  38. clearskies_aws/input_outputs/lambda_alb.py +53 -0
  39. clearskies_aws/input_outputs/lambda_api_gateway.py +106 -88
  40. clearskies_aws/input_outputs/lambda_api_gateway_web_socket.py +69 -6
  41. clearskies_aws/input_outputs/lambda_input_output.py +87 -0
  42. clearskies_aws/input_outputs/lambda_invocation.py +77 -26
  43. clearskies_aws/input_outputs/lambda_sns.py +66 -39
  44. clearskies_aws/input_outputs/lambda_sqs_standard.py +70 -40
  45. clearskies_aws/mocks/actions/ses.py +25 -19
  46. clearskies_aws/mocks/actions/sns.py +18 -12
  47. clearskies_aws/mocks/actions/sqs.py +18 -12
  48. clearskies_aws/mocks/actions/step_function.py +19 -13
  49. clearskies_aws/models/__init__.py +0 -0
  50. clearskies_aws/models/web_socket_connection_model.py +182 -0
  51. clearskies_aws/secrets/__init__.py +13 -7
  52. clearskies_aws/secrets/additional_configs/__init__.py +10 -2
  53. clearskies_aws/secrets/additional_configs/iam_db_auth.py +26 -16
  54. clearskies_aws/secrets/additional_configs/iam_db_auth_with_ssm.py +43 -39
  55. clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +30 -31
  56. clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssm_bastion.py +70 -49
  57. clearskies_aws/secrets/akeyless_with_ssm_cache.py +32 -18
  58. clearskies_aws/secrets/parameter_store.py +34 -32
  59. clearskies_aws/secrets/secrets.py +16 -0
  60. clearskies_aws/secrets/secrets_manager.py +78 -57
  61. clear_skies_aws-1.10.2.dist-info/LICENSE +0 -7
  62. clear_skies_aws-1.10.2.dist-info/RECORD +0 -71
  63. clearskies_aws/actions/assume_role_test.py +0 -72
  64. clearskies_aws/actions/ses_test.py +0 -89
  65. clearskies_aws/actions/sns_test.py +0 -77
  66. clearskies_aws/actions/sqs_test.py +0 -127
  67. clearskies_aws/actions/step_function_test.py +0 -103
  68. clearskies_aws/backends/dynamo_db_backend_test.py +0 -300
  69. clearskies_aws/backends/dynamo_db_condition_parser_test.py +0 -266
  70. clearskies_aws/backends/dynamo_db_parti_ql_backend_test.py +0 -544
  71. clearskies_aws/backends/sqs_backend_test.py +0 -31
  72. clearskies_aws/contexts/cli.py +0 -19
  73. clearskies_aws/contexts/cli_websocket_mock.py +0 -33
  74. clearskies_aws/contexts/lambda_elb.py +0 -30
  75. clearskies_aws/contexts/lambda_http_gateway.py +0 -30
  76. clearskies_aws/contexts/lambda_sqs_standard_partial_batch_test.py +0 -66
  77. clearskies_aws/contexts/wsgi.py +0 -19
  78. clearskies_aws/di/standard_dependencies.py +0 -60
  79. clearskies_aws/handlers/simple_body_routing.py +0 -39
  80. clearskies_aws/input_outputs/lambda_api_gateway_test.py +0 -87
  81. clearskies_aws/input_outputs/lambda_elb.py +0 -21
  82. clearskies_aws/input_outputs/lambda_http_gateway.py +0 -12
  83. clearskies_aws/secrets/parameter_store_test.py +0 -18
  84. clearskies_aws/secrets/secrets_manager_test.py +0 -18
  85. clearskies_aws/web_socket_connection_model.py +0 -43
  86. clearskies_aws/{handlers → endpoints}/__init__.py +1 -1
@@ -1,46 +1,48 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: clear-skies-aws
3
- Version: 1.10.2
3
+ Version: 2.0.2
4
4
  Summary: clearskies bindings for working in AWS
5
- License: MIT
6
- Author: Conor Mancone
7
- Author-email: cmancone@gmail.com
8
- Requires-Python: >=3.10,<4.0
5
+ Project-URL: Repository, https://github.com/clearskies-py/clearskies-aws
6
+ Project-URL: Issues, https://github.com/clearskies-py/clearskies-aws/issues
7
+ Project-URL: Changelog, https://github.com/clearskies-py/clearskies-aws/blob/main/CHANGELOG.md
8
+ Project-URL: Documentation, https://clearskies.info/modules/clearskies-aws/
9
+ Author: tnijboer
10
+ Author-email: Conor Mancone <cmancone@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
9
15
  Classifier: License :: OSI Approved :: MIT License
10
16
  Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Python: <4.0,>=3.11
18
+ Requires-Dist: boto3<2.0.0,>=1.26.148
19
+ Requires-Dist: clear-skies<3.0.0,>=2.0.2
20
+ Requires-Dist: types-boto3[dynamodb,sns,sqs]<2.0.0,>=1.38.13
15
21
  Provides-Extra: akeyless
22
+ Requires-Dist: akeyless-cloud-id<0.5.0,>=0.2.3; extra == 'akeyless'
23
+ Requires-Dist: akeyless<6.0.0,>=5.0.0; extra == 'akeyless'
16
24
  Provides-Extra: ses
17
- Requires-Dist: akeyless (>=4.0.0,<5.0.0) ; extra == "akeyless"
18
- Requires-Dist: akeyless-cloud-id (>=0.2.3,<0.3.0) ; extra == "akeyless"
19
- Requires-Dist: boto3 (>=1.26.148,<2.0.0)
20
- Requires-Dist: clear-skies (>=1.14.4,<2.0.0)
21
- Requires-Dist: jinja2 (>=3.1.2,<4.0.0) ; extra == "ses"
22
- Requires-Dist: types-boto3[dynamodb,sns,sqs] (>=1.38.13,<2.0.0)
23
- Project-URL: Repository, https://github.com/cmancone/clearskies-aws
25
+ Requires-Dist: jinja2<4.0.0,>=3.1.2; extra == 'ses'
24
26
  Description-Content-Type: text/markdown
25
27
 
26
28
  # clearskies-aws
27
29
 
28
30
  clearskies bindings for working in AWS, which means additional:
29
31
 
30
- - backends (DynamoDB, SQS)
31
- - Secret/environment integrations (parameter store/secret manager)
32
- - DB connectivity via IAM auth
33
- - Contexts (ALB, HTTP API Gateway, Rest API Gateway, direct Lambda invocation, lambda+SQS)
32
+ - backends (DynamoDB, SQS)
33
+ - Secret/environment integrations (parameter store/secret manager)
34
+ - DB connectivity via IAM auth
35
+ - Contexts (ALB, HTTP API Gateway, Rest API Gateway, direct Lambda invocation, lambda+SQS)
34
36
 
35
- # Installation, Documentation, and Usage
37
+ ## Installation, Documentation, and Usage
36
38
 
37
39
  To install:
38
40
 
39
- ```
41
+ ```shell
40
42
  pip3 install clear-skies-aws
41
43
  ```
42
44
 
43
- # Usage
45
+ ## Usage
44
46
 
45
47
  Anytime you use a context from `clearskies-aws`, the default dependencies are adjust to:
46
48
 
@@ -49,17 +51,17 @@ Anytime you use a context from `clearskies-aws`, the default dependencies are ad
49
51
 
50
52
  In both cases you must provide the AWS region for your resources, which you do by setting the `AWS_REGION` environment variable (either in an actual environment variable or in your `.env` file).
51
53
 
52
- ## Paramter Store
54
+ ### Parameter Store
53
55
 
54
56
  To use the SSM parameter store you just inject the `secrets` variable into your callables:
55
57
 
56
- ```
58
+ ```python
57
59
  import clearskies_aws
58
60
 
59
61
  def parameter_store_demo(secrets):
60
62
  return secrets.get('/path/to/parameter')
61
63
 
62
- execute_demo_in_elb = clearskies_aws.contexts.lambda_elb(parameter_store_demo)
64
+ execute_demo_in_elb = clearskies_aws.contexts.lambda_alb(parameter_store_demo)
63
65
 
64
66
  def lambda_handler(event, context):
65
67
  return execute_demo_in_elb(event, context)
@@ -67,14 +69,14 @@ def lambda_handler(event, context):
67
69
 
68
70
  Also, per default behavior, clearskies can fetch things from your secret manager if specified in your environment/.env file. For instance, if your database password is stored in parameter store, then you can reference it from your `.env` file with a standard cursor backend:
69
71
 
70
- ```
72
+ ```env
71
73
  db_host = "path-to-aws.rds"
72
74
  db_username = "sql_username"
73
75
  db_password = "secret://path/to/password/in/parameter/store"
74
76
  db_database = "sql_database_name"
75
77
  ```
76
78
 
77
- ## Secret Manager
79
+ ### Secret Manager
78
80
 
79
81
  If desired, you can swap out the parameter store integration for secret manager. Just remember that you can configure parameter store to fetch secrets from secret manager, so you might be best off doing that and sticking with the default parameter store integration. Still, if you want to use secret manager, you just configure it in your application or context:
80
82
 
@@ -93,7 +95,7 @@ def lambda_handler(event, context):
93
95
  return execute_demo_in_elb(event, context)
94
96
  ```
95
97
 
96
- ## Contexts
98
+ ### Contexts
97
99
 
98
100
  clearskies_aws adds the following contexts:
99
101
 
@@ -105,7 +107,7 @@ clearskies_aws adds the following contexts:
105
107
  | `clearskies_aws.contexts.lambda_inocation` | Lambdas invoked directly |
106
108
  | `clearskies_aws.contexts.lambda_sqs_standard_partial_batch` | Lambdas attached to an SQS queue |
107
109
 
108
- ### Lambdas+SQS
110
+ #### Lambdas+SQS
109
111
 
110
112
  Here's a simple example of using the Lambda+SQS context:
111
113
 
@@ -125,7 +127,7 @@ See [the AWS docs](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html).
125
127
 
126
128
  Note that, unlike other contexts, the Lambda+SQS context really only works with a simple callable. Routing and other handlers don't make much sense here. Keep in mind that, before invoking the Lambda, AWS may batch up records together in arbitrary ways. The context will take care of this and will invoke your callable once **for each record in the AWS event** - not once for the event. `request_data` will be populated with the actual message for the event. In addition, it assumes that a JSON message was sent to the queue, so `request_data` will be an object/list/etc, rather than a string. This is intended to be used with [partial batching](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting). Therefore, if your function raises an error, the context will catch it, return a failure response for the cooresponding message, and then continue processing any other messages in the batch.
127
129
 
128
- ## SQS Backend
130
+ ### SQS Backend
129
131
 
130
132
  To use the SQS backend just declare it for your model, set the table name to return the queue url, and execute a "create" operation to send data to the queue. Note that the SQS backend is write-only: you can "create" records (resulting in a message being sent to the queue), but you can't read data back out. The way the queue system in SQS works is just too different than a standard database for that to make sense in the context of a clearskies model.
131
133
 
@@ -164,7 +166,7 @@ if __name__ == '__main__':
164
166
  cli()
165
167
  ```
166
168
 
167
- ## IAM DB Auth
169
+ ### IAM DB Auth
168
170
 
169
171
  For non-serverless RDS databases, AWS supports login via IAM. You have to provide a few additional details in your environment to make this work:
170
172
 
@@ -195,7 +197,6 @@ def lambda_handler(event, context):
195
197
 
196
198
  Of course normally you wouldn't want to interact with it directly. Adding `IAMDBAuth` to your `additional_configs` and setting up the necessary environemnt variables will be sufficient that any models that use the `cursor_backend` will connect via IAM DB Auth, rather than using hard-coded passwords.
197
199
 
198
- ## IAM DB Auth with SSM Bastion
200
+ ### IAM DB Auth with SSM Bastion
199
201
 
200
202
  Coming shortly
201
-
@@ -0,0 +1,63 @@
1
+ clearskies_aws/__init__.py,sha256=LAzXoPm5wVRdxUoQIWuBS_c71t9IT_iq-mIh338154o,297
2
+ clearskies_aws/actions/__init__.py,sha256=YsIi3ZTdByu4R7I77uOAXDE5hzB31J_tRrIoTxe_bjo,371
3
+ clearskies_aws/actions/action_aws.py,sha256=JMogBFIrN72h5oBQLbyMy0LmfVLrqvWCYLQDml1qO4M,4674
4
+ clearskies_aws/actions/assume_role.py,sha256=XNxbVju460aBMS8NQhY80eoNVQgZRJ6-OydsNOx3neA,4319
5
+ clearskies_aws/actions/ses.py,sha256=Cu8USID8vy2IZC6sFOIQRzv8a0LCMvYG15yn0l-fl5g,8431
6
+ clearskies_aws/actions/sns.py,sha256=YS1TbEwtU-0lDbjG2HyTBs2J-ML5OL3ModAiGTMeK-c,2205
7
+ clearskies_aws/actions/sqs.py,sha256=r0z8njU87n09UgAq3l34JuNIbaBE85D_z8IE6ciIs9Q,3359
8
+ clearskies_aws/actions/step_function.py,sha256=Y6tGbQJIAD_IwV9ohwYfuv3vqtryTwpFTNGUFgdj_DQ,2689
9
+ clearskies_aws/backends/__init__.py,sha256=LgMNrf2yD9_PZBGbfs3yQGWM0NelSwk9GO73NfGwc44,587
10
+ clearskies_aws/backends/backend.py,sha256=WpsoT0pZOdilvtOkbiNtk6DoOEzmjyWcCDfUCWOlToc,4316
11
+ clearskies_aws/backends/dynamo_db_backend.py,sha256=cTlbSpMiJ-0YILeHRrMZ6u4blRl_76hmemZZO9BwNN4,29396
12
+ clearskies_aws/backends/dynamo_db_condition_parser.py,sha256=OipIlFpcfS2GQiGpge6ZFX4NZNfNtHF87qi9g3yZgIU,12622
13
+ clearskies_aws/backends/dynamo_db_parti_ql_backend.py,sha256=x1pLNTUsTjCxi1SDryr9_uhL-AQJS7ksP5bvQpnhaC8,46081
14
+ clearskies_aws/backends/sqs_backend.py,sha256=kHTzgBwpYzV31UcGaoSUcC_7eZEwm-GsCHvXFM1OLT0,2152
15
+ clearskies_aws/configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ clearskies_aws/contexts/__init__.py,sha256=sdcIT85OXqwwo8CcBYuyNcN6kvkwv1Ph8MTwuSi4Bnk,767
17
+ clearskies_aws/contexts/cli_web_socket_mock.py,sha256=ZjOhOtQHJ4Vf9V1Bkole6JiGyP1CLTzPqwTrLiiOi0A,660
18
+ clearskies_aws/contexts/lambda_alb.py,sha256=9eLemimudZ4WsWGarONIhoiFnlk_fBygQ6XwJb7NrbY,3237
19
+ clearskies_aws/contexts/lambda_api_gateway.py,sha256=K8sKDV2JtXbzcDy9SOd7kMveuD6t5VGxls2iDMiVhXY,2787
20
+ clearskies_aws/contexts/lambda_api_gateway_web_socket.py,sha256=t3dLRT3s37xHazMa-KVOSWF-0OaUpGQ4an-olbeeJUw,3238
21
+ clearskies_aws/contexts/lambda_invocation.py,sha256=j3AhSXMHRwKufOSTUjhMyeFk4sO_Y4BlX4ECCFvMudw,538
22
+ clearskies_aws/contexts/lambda_sns.py,sha256=FFOIyyCQFKvYsolpf8zlVitdceRkgvEjds3GCXSJjdk,719
23
+ clearskies_aws/contexts/lambda_sqs_standard_partial_batch.py,sha256=kWl3rFtsAbSkadRLZunN20oXvCQpZJFcDhv3VMMWrCg,1093
24
+ clearskies_aws/di/__init__.py,sha256=pLHSIKxS1oELOgttRuwM0yXdJRxjZKXQ6tPxme2db0U,222
25
+ clearskies_aws/di/aws_additional_config_auto_import.py,sha256=qc9AUlFdF9jhAzS99esyvgY1MiW7mLz45fATK7Yp0rg,1271
26
+ clearskies_aws/di/inject/__init__.py,sha256=5_x5_BBQwC6J4k5YLdTm1DfIDM-95zXz1L5a1nMrlrY,186
27
+ clearskies_aws/di/inject/boto3.py,sha256=7qcn5N-RnUKiCd1U31JAjQHF6NDudS4KyBLT0krUD-Y,404
28
+ clearskies_aws/di/inject/boto3_session.py,sha256=11UYHz5kgrrx5lawoYaOFBm-QIoa45YUCMAOn4gT8Jo,383
29
+ clearskies_aws/di/inject/parameter_store.py,sha256=g0uAVwQEywLO9bCcYLbDKuyYnYgVyrfcYsOBJWYGads,475
30
+ clearskies_aws/endpoints/__init__.py,sha256=A2e3zCI8Ywg95WcTk1f92fpmlJ6eD4mTfcR43yX9sow,112
31
+ clearskies_aws/endpoints/secrets_manager_rotation.py,sha256=CqtE7pJ1FiPStRjMI1WsflcYXgcr-miRUE-IU1UKmnk,7764
32
+ clearskies_aws/endpoints/simple_body_routing.py,sha256=B3fnfxUEMuNpzc26Pzly6618DFU9fpaCk8KhTGSaptE,1181
33
+ clearskies_aws/input_outputs/__init__.py,sha256=83rhCp7knun2WB4Pd53H8KvVgM_4_Lt0YuD2Gvo2UPk,755
34
+ clearskies_aws/input_outputs/cli_web_socket_mock.py,sha256=a96M1vnUfpe0YL04iSFpV_oXG6IkygRd710CDo72wc4,496
35
+ clearskies_aws/input_outputs/lambda_alb.py,sha256=iYooG5AlkrQQgzSt304A5_u_UhuqYh-9PeLvFdGM_Eg,2013
36
+ clearskies_aws/input_outputs/lambda_api_gateway.py,sha256=n5XiaxmaFKJ9wMQcNQwizpjcA-L_bdLk1aUk-QyO58w,4672
37
+ clearskies_aws/input_outputs/lambda_api_gateway_web_socket.py,sha256=P9cMrOxRlezUh7OIqGrV_34amksI6n_1ZPYujSLY_so,2702
38
+ clearskies_aws/input_outputs/lambda_input_output.py,sha256=71sW2vQi-yCf0wE8DGso0Zy1G7cn5D-gnEELIvEnbiw,2743
39
+ clearskies_aws/input_outputs/lambda_invocation.py,sha256=y8dPkjt9rvSJd2tkctdtM1-q_SnRPR_bXc9aySjRgdE,2800
40
+ clearskies_aws/input_outputs/lambda_sns.py,sha256=n04gS8bgo3sX8EZTkBvdCykm5dlV4lloc7IoPv71_T8,2657
41
+ clearskies_aws/input_outputs/lambda_sqs_standard.py,sha256=ubrSdU0RTHIURLk_kgKs3Gt7LcxaUlRBdA67169qHlA,2880
42
+ clearskies_aws/mocks/__init__.py,sha256=mn764gINN667tYoJfnsM6HjAAhCsO_kZ6E-fUwdLY50,22
43
+ clearskies_aws/mocks/actions/__init__.py,sha256=to1r8B365Et2PRVfUWWnJGt7Hdr8vwwQuNyZvTSTP6g,152
44
+ clearskies_aws/mocks/actions/ses.py,sha256=KsII9ggU364BQoxgHfO2rxi6tjVsdnwJyMhtclOhWLQ,998
45
+ clearskies_aws/mocks/actions/sns.py,sha256=yGY3V0_htOZ3y8VTLdznoMSUQZvnjulQbrR5z_-0fXQ,706
46
+ clearskies_aws/mocks/actions/sqs.py,sha256=y0Vq7IMbjlfT5JMNHfbPsq9XVZhUF-G0kdXzQnPzyUA,710
47
+ clearskies_aws/mocks/actions/step_function.py,sha256=ENEVy8Ai3vPymbQre5aWa5z2McBjlnopfsLxdO7oEbc,937
48
+ clearskies_aws/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ clearskies_aws/models/web_socket_connection_model.py,sha256=5M1qfQHKuWMYPUDkwT48QPo2ROey7koizvWLfapsfow,7492
50
+ clearskies_aws/secrets/__init__.py,sha256=0mqYja2ETBHJh4b3jgRhhJV1uGdZc9S7cUvcV5QByPs,445
51
+ clearskies_aws/secrets/akeyless_with_ssm_cache.py,sha256=32HUS1KQ5F6Fu70HDtojqDL7VZvP_YDgbWLTTmNJvPA,2073
52
+ clearskies_aws/secrets/parameter_store.py,sha256=nMpkbUnxHGcCoMD5T-weCS13f1RZA7ZHl24O7qXaZLE,1882
53
+ clearskies_aws/secrets/secrets.py,sha256=aDMPj-tuXdRhh8YKMnsJe9V_VLrD8Cru-xUKs8cyDIY,485
54
+ clearskies_aws/secrets/secrets_manager.py,sha256=hK10lVmEFJltTv7h2AkYR3ySCVXx1JVy56jWU1hyYso,3708
55
+ clearskies_aws/secrets/additional_configs/__init__.py,sha256=0NFOMVod8tte_K0Jq1Qf7_DDBvp6aEE4wF4hddQaW8w,1927
56
+ clearskies_aws/secrets/additional_configs/iam_db_auth.py,sha256=PwyiLaacpRfhBKzQBdvGWHUYf5Ymth1sG2ly7Z6RoR0,1238
57
+ clearskies_aws/secrets/additional_configs/iam_db_auth_with_ssm.py,sha256=ABY29X-YvrE6vvNo6kVdf4DqyRNq5cFR5SfK7MNkltE,3463
58
+ clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py,sha256=mLaplwvJLSbGh6oXgdOKL9Mv-6hLv5OUYCfEwHbHvLE,3700
59
+ clearskies_aws/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssm_bastion.py,sha256=2VHOwto4I9gBwrpd2HGpL-Wr0T2S-jFjUhe2Ib8hNJ8,6596
60
+ clear_skies_aws-2.0.2.dist-info/METADATA,sha256=BcwJmkUhC-KD2QwepuW2kAeU6IRITpMOKrKCgAO2_b4,8972
61
+ clear_skies_aws-2.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
62
+ clear_skies_aws-2.0.2.dist-info/licenses/LICENSE,sha256=MkEX8JF8kZxdyBpTTcB0YTd-xZpWnHvbRlw-pQh8u58,1069
63
+ clear_skies_aws-2.0.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025, Tom Nijboer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,2 +1,15 @@
1
- from . import actions, backends, contexts, handlers, mocks, secrets
2
- from .web_socket_connection_model import WebSocketConnectionModel
1
+ from __future__ import annotations
2
+
3
+ from clearskies_aws import actions, backends, contexts, di, endpoints, input_outputs, mocks, models, secrets
4
+
5
+ __all__ = [
6
+ "models",
7
+ "actions",
8
+ "backends",
9
+ "contexts",
10
+ "di",
11
+ "endpoints",
12
+ "input_outputs",
13
+ "mocks",
14
+ "secrets",
15
+ ]
@@ -1,108 +1,15 @@
1
- import clearskies
1
+ from __future__ import annotations
2
2
 
3
- from typing import Optional, Callable, Union
3
+ from clearskies_aws.actions.assume_role import AssumeRole
4
+ from clearskies_aws.actions.ses import SES
5
+ from clearskies_aws.actions.sns import SNS
6
+ from clearskies_aws.actions.sqs import SQS
7
+ from clearskies_aws.actions.step_function import StepFunction
4
8
 
5
- from .assume_role import AssumeRole
6
- from .ses import SES
7
- from .sns import SNS
8
- from .sqs import SQS
9
- from .step_function import StepFunction
10
- def ses(
11
- sender,
12
- to=None,
13
- cc=None,
14
- bcc=None,
15
- subject=None,
16
- message=None,
17
- subject_template=None,
18
- message_template=None,
19
- subject_template_file=None,
20
- message_template_file=None,
21
- assume_role=None,
22
- dependencies_for_template=None,
23
- when=None,
24
- ):
25
- return clearskies.BindingConfig(
26
- SES,
27
- sender,
28
- to=to,
29
- cc=cc,
30
- bcc=bcc,
31
- subject=subject,
32
- subject_template=subject_template,
33
- subject_template_file=subject_template_file,
34
- message=message,
35
- message_template=message_template,
36
- message_template_file=message_template_file,
37
- assume_role=assume_role,
38
- dependencies_for_template=dependencies_for_template,
39
- when=when,
40
- )
41
- def sns(
42
- topic=None,
43
- topic_environment_key=None,
44
- topic_callable=None,
45
- message_callable=None,
46
- when=None,
47
- ):
48
- return clearskies.BindingConfig(
49
- SNS,
50
- topic=topic,
51
- topic_environment_key=topic_environment_key,
52
- topic_callable=topic_callable,
53
- message_callable=message_callable,
54
- when=when,
55
- )
56
- def sqs(
57
- queue_url: str = '',
58
- queue_url_environment_key: str = '',
59
- queue_url_callable: Callable = '',
60
- message_callable: Callable = None,
61
- when: Callable = None,
62
- assume_role=None,
63
- message_group_id: Optional[Union[Callable, str]]=None,
64
- ):
65
- return clearskies.BindingConfig(
66
- SQS,
67
- queue_url=queue_url,
68
- queue_url_environment_key=queue_url_environment_key,
69
- queue_url_callable=queue_url_callable,
70
- message_callable=message_callable,
71
- when=when,
72
- assume_role=assume_role,
73
- message_group_id=message_group_id,
74
- )
75
- def step_function(
76
- arn: str = "",
77
- arn_environment_key: str = "",
78
- arn_callable: Optional[Callable] = None,
79
- message_callable: Optional[Callable] = None,
80
- when: Optional[Callable] = None,
81
- assume_role: Optional[AssumeRole] = None,
82
- column_to_store_execution_arn: Optional[str] = None,
83
- ):
84
- return clearskies.BindingConfig(
85
- StepFunction,
86
- arn=arn,
87
- arn_environment_key=arn_environment_key,
88
- arn_callable=arn_callable,
89
- message_callable=message_callable,
90
- when=when,
91
- assume_role=assume_role,
92
- column_to_store_execution_arn=column_to_store_execution_arn,
93
- )
94
- def assume_role(
95
- role_arn: str,
96
- external_id: str = "",
97
- role_session_name: str = "",
98
- duration: int = 3600,
99
- source: Optional[AssumeRole] = None,
100
- ):
101
- return AssumeRole(
102
- role_arn,
103
- external_id=external_id,
104
- role_session_name=role_session_name,
105
- duration=duration,
106
- source=source,
107
- )
108
- __all__ = [assume_role, AssumeRole, ses, SES, sns, SNS, step_function, StepFunction, sqs, SQS]
9
+ __all__ = [
10
+ "AssumeRole",
11
+ "SES",
12
+ "SNS",
13
+ "SQS",
14
+ "StepFunction",
15
+ ]
@@ -1,117 +1,134 @@
1
- import boto3
1
+ from __future__ import annotations
2
+
2
3
  import json
3
4
  import logging
4
-
5
5
  from abc import ABC
6
- from boto3 import client
6
+ from collections import OrderedDict
7
+ from types import ModuleType
8
+ from typing import Callable, Generic, TypeVar
9
+
10
+ from botocore.client import BaseClient
7
11
  from botocore.exceptions import ClientError
8
- from clearskies.environment import Environment
9
- from clearskies.models import Models
12
+ from clearskies.action import Action
13
+ from clearskies.configs import Boolean, String
14
+ from clearskies.configs import Callable as CallableConfig
15
+ from clearskies.configurable import Configurable
16
+ from clearskies.decorators import parameters_to_properties
17
+ from clearskies.di.inject import Di, Environment
18
+ from clearskies.di.injectable_properties import InjectableProperties
10
19
  from clearskies.functional import string
11
- from collections import OrderedDict
12
- from typing import Callable, Optional
20
+ from clearskies.model import Model
21
+
22
+ from clearskies_aws.di import inject
13
23
 
14
- from ..di import StandardDependencies
15
24
  from .assume_role import AssumeRole
16
- class ActionAws(ABC):
17
25
 
18
- _logging = logging.getLogger(__name__)
19
- _client: Optional[boto3.client] = None
20
- _name: Optional[str] = None
26
+ ClientType = TypeVar("ClientType", bound=BaseClient)
21
27
 
22
- def __init__(self, environment: Environment, boto3: boto3, di: StandardDependencies) -> None:
23
- """Setup action."""
24
- self.environment = environment
25
- self.boto3 = boto3
26
- self.di = di
27
28
 
28
- def configure(
29
- self,
30
- message_callable: Optional[Callable] = None,
31
- when: Optional[Callable] = None,
32
- assume_role: Optional[AssumeRole] = None,
33
- ) -> None:
34
- """Configues the Action."""
35
- self.when = when
36
- self.message_callable = message_callable
37
- self.assume_role = assume_role
29
+ class ActionAws(Generic[ClientType], Action, Configurable, InjectableProperties):
30
+ logging = logging.getLogger(__name__)
31
+ boto3 = inject.Boto3()
32
+ environment = Environment()
33
+ di = Di()
34
+
35
+ client: ClientType
38
36
 
39
- if self.message_callable and not callable(self.message_callable):
40
- raise ValueError(
41
- "'message_callable' should be a callable that returns the message for the queue, but a callable was not passed."
42
- )
37
+ service_name = String(required=True)
43
38
 
44
- if when and not callable(when):
45
- raise ValueError("'when' must be a callable but something else was found")
39
+ message_callable = CallableConfig(required=False, default=None)
46
40
 
47
- if not self._name:
48
- raise ValueError(f"Name of client not set.")
41
+ when = CallableConfig(required=False, default=None)
49
42
 
50
- if not self.environment.get('AWS_REGION', True) and not self.environment.get('AWS_DEFAULT_REGION', True):
51
- raise ValueError("You must set either the AWS_REGION or AWS_DEFAULT_REGION environment variable when using AWS actions")
43
+ assume_role: AssumeRole | None = None
52
44
 
53
- def __call__(self, model: Models) -> None:
45
+ region = String(required=False)
46
+
47
+ can_cache = Boolean(default=True)
48
+
49
+ @parameters_to_properties
50
+ def __init__(
51
+ self,
52
+ service_name: str,
53
+ message_callable: Callable | None = None,
54
+ when: Callable | None = None,
55
+ assume_role: AssumeRole | None = None,
56
+ region: str | None = None,
57
+ ) -> None:
58
+ """Set up the AWS action."""
59
+
60
+ # def configure(self, **kwargs):
61
+ # """Configure the action with additional parameters."""
62
+ # # Finalize configuration properties from Configurable
63
+ # Configurable.finalize_and_validate_configuration(self)
64
+
65
+ # # Handle any additional kwargs by setting them as attributes
66
+ # for key, value in kwargs.items():
67
+ # if hasattr(self, key):
68
+ # setattr(self, key, value)
69
+
70
+ def __call__(self, model: Model) -> None:
54
71
  """Send a notification as configured."""
55
72
  if self.when and not self.di.call_function(self.when, model=model):
56
73
  return
57
74
 
58
75
  try:
59
- client = self._getClient()
76
+ client = self._get_client()
60
77
  self._execute_action(client, model)
61
78
  except ClientError as e:
62
- self._logging.exception(f"Failed to retrieve client for {self._name}")
79
+ self.logging.exception(f"Failed to retrieve client for {self.__class__.__name__} action.")
63
80
  raise e
64
81
 
65
- def _getClient(self, region=None) -> boto3.client:
82
+ def _get_client(self) -> ClientType:
66
83
  """Retrieve the boto3 client."""
67
- can_cache = not region
68
- if self._client and can_cache:
69
- return self._client
84
+ if hasattr(self, "client") and self.client and self.can_cache:
85
+ return self.client
70
86
 
71
87
  if self.assume_role:
72
88
  boto3 = self.assume_role(self.boto3)
73
89
  else:
74
90
  boto3 = self.boto3
75
91
 
76
- if not region:
77
- region = self.default_region()
78
- if region:
79
- client = boto3.client(self._name, region_name=region)
92
+ if not self.region:
93
+ self.region = self.default_region()
94
+ if self.region:
95
+ client = boto3.client(self.service_name, region_name=self.region)
80
96
  else:
81
- client = boto3.client(self._name)
97
+ client = boto3.client(self.service_name)
82
98
 
83
- if can_cache:
84
- self._client = client
99
+ if self.can_cache:
100
+ self.client = client
85
101
  return client
86
102
 
87
103
  def default_region(self):
88
- region = self.environment.get('AWS_REGION', silent=True)
104
+ region = self.environment.get("AWS_REGION", silent=True)
89
105
  if region:
90
106
  return region
91
- region = self.environment.get('DEFAULT_AWS_REGION', silent=True)
107
+ region = self.environment.get("DEFAULT_AWS_REGION", silent=True)
92
108
  if region:
93
109
  return region
94
110
  return None
95
111
 
96
- def _execute_action(self, client: boto3.client, model: Models) -> None:
112
+ def _execute_action(self, client: ClientType, model: Model) -> None:
97
113
  """Run the action."""
98
114
  pass
99
115
 
100
- def get_message_body(self, model: Models) -> str:
116
+ def get_message_body(self, model: Model) -> str:
101
117
  """Retrieve the message for the action."""
102
118
  if self.message_callable:
103
119
  result = self.di.call_function(self.message_callable, model=model)
104
120
  if isinstance(result, dict) or isinstance(result, list):
105
121
  return json.dumps(result, default=string.datetime_to_iso)
106
122
  if not isinstance(result, str):
123
+ callable_name = getattr(self.message_callable, "__name__", str(self.message_callable))
107
124
  raise TypeError(
108
125
  f"The return value from the message callable for the {__name__} action must be a string, dictionary, or list. I received a "
109
- + f"{type(result)} after calling '{self.message_callable.__name__}'"
126
+ + f"{type(result)} after calling '{callable_name}'"
110
127
  )
111
128
  return result
112
129
 
113
130
  model_data = OrderedDict()
114
- for (column_name, column) in model.columns().items():
131
+ for column_name, column in model.get_columns().items():
115
132
  if not column.is_readable:
116
133
  continue
117
134
  model_data.update(column.to_json(model))