capo-codedeploy 0.1.0__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 (472) hide show
  1. capo_codedeploy/__init__.py +70 -0
  2. capo_codedeploy/_async.py +25 -0
  3. capo_codedeploy/_auth/_identity.py +16 -0
  4. capo_codedeploy/_auth/_providers.py +886 -0
  5. capo_codedeploy/_auth/_signers.py +88 -0
  6. capo_codedeploy/_auth/_sigv4.py +434 -0
  7. capo_codedeploy/_auth/_zapros_handler.py +80 -0
  8. capo_codedeploy/_iter.py +113 -0
  9. capo_codedeploy/_operations/code_deploy_20141006/add_tags_to_on_premises_instances.py +153 -0
  10. capo_codedeploy/_operations/code_deploy_20141006/batch_get_application_revisions.py +173 -0
  11. capo_codedeploy/_operations/code_deploy_20141006/batch_get_applications.py +163 -0
  12. capo_codedeploy/_operations/code_deploy_20141006/batch_get_deployment_groups.py +178 -0
  13. capo_codedeploy/_operations/code_deploy_20141006/batch_get_deployment_instances.py +178 -0
  14. capo_codedeploy/_operations/code_deploy_20141006/batch_get_deployment_targets.py +188 -0
  15. capo_codedeploy/_operations/code_deploy_20141006/batch_get_deployments.py +158 -0
  16. capo_codedeploy/_operations/code_deploy_20141006/batch_get_on_premises_instances.py +158 -0
  17. capo_codedeploy/_operations/code_deploy_20141006/continue_deployment.py +155 -0
  18. capo_codedeploy/_operations/code_deploy_20141006/create_application.py +175 -0
  19. capo_codedeploy/_operations/code_deploy_20141006/create_deployment.py +278 -0
  20. capo_codedeploy/_operations/code_deploy_20141006/create_deployment_config.py +185 -0
  21. capo_codedeploy/_operations/code_deploy_20141006/create_deployment_group.py +320 -0
  22. capo_codedeploy/_operations/code_deploy_20141006/delete_application.py +129 -0
  23. capo_codedeploy/_operations/code_deploy_20141006/delete_deployment_config.py +136 -0
  24. capo_codedeploy/_operations/code_deploy_20141006/delete_deployment_group.py +167 -0
  25. capo_codedeploy/_operations/code_deploy_20141006/delete_git_hub_account_token.py +166 -0
  26. capo_codedeploy/_operations/code_deploy_20141006/delete_resources_by_external_id.py +137 -0
  27. capo_codedeploy/_operations/code_deploy_20141006/deregister_on_premises_instance.py +126 -0
  28. capo_codedeploy/_operations/code_deploy_20141006/get_application.py +157 -0
  29. capo_codedeploy/_operations/code_deploy_20141006/get_application_revision.py +173 -0
  30. capo_codedeploy/_operations/code_deploy_20141006/get_deployment.py +157 -0
  31. capo_codedeploy/_operations/code_deploy_20141006/get_deployment_config.py +162 -0
  32. capo_codedeploy/_operations/code_deploy_20141006/get_deployment_group.py +179 -0
  33. capo_codedeploy/_operations/code_deploy_20141006/get_deployment_instance.py +177 -0
  34. capo_codedeploy/_operations/code_deploy_20141006/get_deployment_target.py +182 -0
  35. capo_codedeploy/_operations/code_deploy_20141006/get_on_premises_instance.py +157 -0
  36. capo_codedeploy/_operations/code_deploy_20141006/list_application_revisions.py +195 -0
  37. capo_codedeploy/_operations/code_deploy_20141006/list_applications.py +149 -0
  38. capo_codedeploy/_operations/code_deploy_20141006/list_deployment_configs.py +147 -0
  39. capo_codedeploy/_operations/code_deploy_20141006/list_deployment_groups.py +162 -0
  40. capo_codedeploy/_operations/code_deploy_20141006/list_deployment_instances.py +198 -0
  41. capo_codedeploy/_operations/code_deploy_20141006/list_deployment_targets.py +188 -0
  42. capo_codedeploy/_operations/code_deploy_20141006/list_deployments.py +199 -0
  43. capo_codedeploy/_operations/code_deploy_20141006/list_git_hub_account_token_names.py +157 -0
  44. capo_codedeploy/_operations/code_deploy_20141006/list_on_premises_instances.py +159 -0
  45. capo_codedeploy/_operations/code_deploy_20141006/list_tags_for_resource.py +157 -0
  46. capo_codedeploy/_operations/code_deploy_20141006/put_lifecycle_event_hook_execution_status.py +177 -0
  47. capo_codedeploy/_operations/code_deploy_20141006/register_application_revision.py +147 -0
  48. capo_codedeploy/_operations/code_deploy_20141006/register_on_premises_instance.py +166 -0
  49. capo_codedeploy/_operations/code_deploy_20141006/remove_tags_from_on_premises_instances.py +153 -0
  50. capo_codedeploy/_operations/code_deploy_20141006/skip_wait_time_for_instance_termination.py +146 -0
  51. capo_codedeploy/_operations/code_deploy_20141006/stop_deployment.py +172 -0
  52. capo_codedeploy/_operations/code_deploy_20141006/tag_resource.py +174 -0
  53. capo_codedeploy/_operations/code_deploy_20141006/untag_resource.py +174 -0
  54. capo_codedeploy/_operations/code_deploy_20141006/update_application.py +134 -0
  55. capo_codedeploy/_operations/code_deploy_20141006/update_deployment_group.py +310 -0
  56. capo_codedeploy/_pagination.py +21 -0
  57. capo_codedeploy/_protocol/__init__.py +1 -0
  58. capo_codedeploy/_protocol/errors.py +93 -0
  59. capo_codedeploy/_protocol/eventstream.py +238 -0
  60. capo_codedeploy/_protocol/serialize.py +47 -0
  61. capo_codedeploy/_protocol/xml.py +33 -0
  62. capo_codedeploy/_rule_engine/__init__.py +0 -0
  63. capo_codedeploy/_rule_engine/_aws_partition.py +160 -0
  64. capo_codedeploy/_rule_engine/_endpoint_rule_set.py +138 -0
  65. capo_codedeploy/_rule_engine/_endpoint_runtime.py +389 -0
  66. capo_codedeploy/_services/_aws_config.py +160 -0
  67. capo_codedeploy/_services/_pipeline.py +198 -0
  68. capo_codedeploy/_services/async_code_deploy.py +3278 -0
  69. capo_codedeploy/_services/code_deploy.py +3229 -0
  70. capo_codedeploy/errors/__init__.py +335 -0
  71. capo_codedeploy/errors/_base.py +94 -0
  72. capo_codedeploy/errors/alarms_limit_exceeded_exception.py +52 -0
  73. capo_codedeploy/errors/application_already_exists_exception.py +54 -0
  74. capo_codedeploy/errors/application_does_not_exist_exception.py +54 -0
  75. capo_codedeploy/errors/application_limit_exceeded_exception.py +54 -0
  76. capo_codedeploy/errors/application_name_required_exception.py +54 -0
  77. capo_codedeploy/errors/arn_not_supported_exception.py +52 -0
  78. capo_codedeploy/errors/batch_limit_exceeded_exception.py +52 -0
  79. capo_codedeploy/errors/bucket_name_filter_required_exception.py +54 -0
  80. capo_codedeploy/errors/deployment_already_completed_exception.py +54 -0
  81. capo_codedeploy/errors/deployment_config_already_exists_exception.py +54 -0
  82. capo_codedeploy/errors/deployment_config_does_not_exist_exception.py +54 -0
  83. capo_codedeploy/errors/deployment_config_in_use_exception.py +54 -0
  84. capo_codedeploy/errors/deployment_config_limit_exceeded_exception.py +54 -0
  85. capo_codedeploy/errors/deployment_config_name_required_exception.py +54 -0
  86. capo_codedeploy/errors/deployment_does_not_exist_exception.py +54 -0
  87. capo_codedeploy/errors/deployment_group_already_exists_exception.py +54 -0
  88. capo_codedeploy/errors/deployment_group_does_not_exist_exception.py +54 -0
  89. capo_codedeploy/errors/deployment_group_limit_exceeded_exception.py +54 -0
  90. capo_codedeploy/errors/deployment_group_name_required_exception.py +54 -0
  91. capo_codedeploy/errors/deployment_id_required_exception.py +54 -0
  92. capo_codedeploy/errors/deployment_is_not_in_ready_state_exception.py +54 -0
  93. capo_codedeploy/errors/deployment_limit_exceeded_exception.py +54 -0
  94. capo_codedeploy/errors/deployment_not_started_exception.py +54 -0
  95. capo_codedeploy/errors/deployment_target_does_not_exist_exception.py +54 -0
  96. capo_codedeploy/errors/deployment_target_id_required_exception.py +54 -0
  97. capo_codedeploy/errors/deployment_target_list_size_exceeded_exception.py +56 -0
  98. capo_codedeploy/errors/description_too_long_exception.py +52 -0
  99. capo_codedeploy/errors/ecs_service_mapping_limit_exceeded_exception.py +54 -0
  100. capo_codedeploy/errors/git_hub_account_token_does_not_exist_exception.py +54 -0
  101. capo_codedeploy/errors/git_hub_account_token_name_required_exception.py +54 -0
  102. capo_codedeploy/errors/iam_arn_required_exception.py +52 -0
  103. capo_codedeploy/errors/iam_session_arn_already_registered_exception.py +54 -0
  104. capo_codedeploy/errors/iam_user_arn_already_registered_exception.py +54 -0
  105. capo_codedeploy/errors/iam_user_arn_required_exception.py +52 -0
  106. capo_codedeploy/errors/instance_does_not_exist_exception.py +54 -0
  107. capo_codedeploy/errors/instance_id_required_exception.py +52 -0
  108. capo_codedeploy/errors/instance_limit_exceeded_exception.py +54 -0
  109. capo_codedeploy/errors/instance_name_already_registered_exception.py +54 -0
  110. capo_codedeploy/errors/instance_name_required_exception.py +54 -0
  111. capo_codedeploy/errors/instance_not_registered_exception.py +54 -0
  112. capo_codedeploy/errors/invalid_alarm_config_exception.py +52 -0
  113. capo_codedeploy/errors/invalid_application_name_exception.py +54 -0
  114. capo_codedeploy/errors/invalid_arn_exception.py +52 -0
  115. capo_codedeploy/errors/invalid_auto_rollback_config_exception.py +54 -0
  116. capo_codedeploy/errors/invalid_auto_scaling_group_exception.py +54 -0
  117. capo_codedeploy/errors/invalid_blue_green_deployment_configuration_exception.py +60 -0
  118. capo_codedeploy/errors/invalid_bucket_name_filter_exception.py +54 -0
  119. capo_codedeploy/errors/invalid_compute_platform_exception.py +54 -0
  120. capo_codedeploy/errors/invalid_deployed_state_filter_exception.py +54 -0
  121. capo_codedeploy/errors/invalid_deployment_config_name_exception.py +54 -0
  122. capo_codedeploy/errors/invalid_deployment_group_name_exception.py +54 -0
  123. capo_codedeploy/errors/invalid_deployment_id_exception.py +52 -0
  124. capo_codedeploy/errors/invalid_deployment_instance_type_exception.py +54 -0
  125. capo_codedeploy/errors/invalid_deployment_status_exception.py +54 -0
  126. capo_codedeploy/errors/invalid_deployment_style_exception.py +54 -0
  127. capo_codedeploy/errors/invalid_deployment_target_id_exception.py +54 -0
  128. capo_codedeploy/errors/invalid_deployment_wait_type_exception.py +54 -0
  129. capo_codedeploy/errors/invalid_ec2_tag_combination_exception.py +54 -0
  130. capo_codedeploy/errors/invalid_ec2_tag_exception.py +52 -0
  131. capo_codedeploy/errors/invalid_ecs_service_exception.py +52 -0
  132. capo_codedeploy/errors/invalid_external_id_exception.py +52 -0
  133. capo_codedeploy/errors/invalid_file_exists_behavior_exception.py +54 -0
  134. capo_codedeploy/errors/invalid_git_hub_account_token_exception.py +54 -0
  135. capo_codedeploy/errors/invalid_git_hub_account_token_name_exception.py +54 -0
  136. capo_codedeploy/errors/invalid_iam_session_arn_exception.py +54 -0
  137. capo_codedeploy/errors/invalid_iam_user_arn_exception.py +52 -0
  138. capo_codedeploy/errors/invalid_ignore_application_stop_failures_value_exception.py +60 -0
  139. capo_codedeploy/errors/invalid_input_exception.py +52 -0
  140. capo_codedeploy/errors/invalid_instance_name_exception.py +52 -0
  141. capo_codedeploy/errors/invalid_instance_status_exception.py +54 -0
  142. capo_codedeploy/errors/invalid_instance_type_exception.py +52 -0
  143. capo_codedeploy/errors/invalid_key_prefix_filter_exception.py +54 -0
  144. capo_codedeploy/errors/invalid_lifecycle_event_hook_execution_id_exception.py +60 -0
  145. capo_codedeploy/errors/invalid_lifecycle_event_hook_execution_status_exception.py +60 -0
  146. capo_codedeploy/errors/invalid_load_balancer_info_exception.py +54 -0
  147. capo_codedeploy/errors/invalid_minimum_healthy_host_value_exception.py +54 -0
  148. capo_codedeploy/errors/invalid_next_token_exception.py +52 -0
  149. capo_codedeploy/errors/invalid_on_premises_tag_combination_exception.py +56 -0
  150. capo_codedeploy/errors/invalid_operation_exception.py +52 -0
  151. capo_codedeploy/errors/invalid_registration_status_exception.py +54 -0
  152. capo_codedeploy/errors/invalid_revision_exception.py +52 -0
  153. capo_codedeploy/errors/invalid_role_exception.py +52 -0
  154. capo_codedeploy/errors/invalid_sort_by_exception.py +52 -0
  155. capo_codedeploy/errors/invalid_sort_order_exception.py +52 -0
  156. capo_codedeploy/errors/invalid_tag_exception.py +52 -0
  157. capo_codedeploy/errors/invalid_tag_filter_exception.py +52 -0
  158. capo_codedeploy/errors/invalid_tags_to_add_exception.py +52 -0
  159. capo_codedeploy/errors/invalid_target_filter_name_exception.py +54 -0
  160. capo_codedeploy/errors/invalid_target_group_pair_exception.py +54 -0
  161. capo_codedeploy/errors/invalid_target_instances_exception.py +54 -0
  162. capo_codedeploy/errors/invalid_time_range_exception.py +52 -0
  163. capo_codedeploy/errors/invalid_traffic_routing_configuration_exception.py +58 -0
  164. capo_codedeploy/errors/invalid_trigger_config_exception.py +54 -0
  165. capo_codedeploy/errors/invalid_update_outdated_instances_only_value_exception.py +60 -0
  166. capo_codedeploy/errors/invalid_zonal_deployment_configuration_exception.py +60 -0
  167. capo_codedeploy/errors/lifecycle_event_already_completed_exception.py +54 -0
  168. capo_codedeploy/errors/lifecycle_hook_limit_exceeded_exception.py +54 -0
  169. capo_codedeploy/errors/multiple_iam_arns_provided_exception.py +54 -0
  170. capo_codedeploy/errors/operation_not_supported_exception.py +54 -0
  171. capo_codedeploy/errors/resource_arn_required_exception.py +52 -0
  172. capo_codedeploy/errors/resource_validation_exception.py +52 -0
  173. capo_codedeploy/errors/revision_does_not_exist_exception.py +54 -0
  174. capo_codedeploy/errors/revision_required_exception.py +52 -0
  175. capo_codedeploy/errors/role_required_exception.py +52 -0
  176. capo_codedeploy/errors/tag_limit_exceeded_exception.py +52 -0
  177. capo_codedeploy/errors/tag_required_exception.py +52 -0
  178. capo_codedeploy/errors/tag_set_list_limit_exceeded_exception.py +54 -0
  179. capo_codedeploy/errors/throttling_exception.py +52 -0
  180. capo_codedeploy/errors/trigger_targets_limit_exceeded_exception.py +54 -0
  181. capo_codedeploy/errors/unsupported_action_for_deployment_type_exception.py +58 -0
  182. capo_codedeploy/py.typed +0 -0
  183. capo_codedeploy/types/_prelude/blob.py +12 -0
  184. capo_codedeploy/types/_prelude/timestamp.py +17 -0
  185. capo_codedeploy/types/add_tags_to_on_premises_instances_input.py +59 -0
  186. capo_codedeploy/types/additional_deployment_status_info.py +5 -0
  187. capo_codedeploy/types/alarm.py +28 -0
  188. capo_codedeploy/types/alarm_configuration.py +51 -0
  189. capo_codedeploy/types/alarm_list.py +29 -0
  190. capo_codedeploy/types/alarm_name.py +5 -0
  191. capo_codedeploy/types/app_spec_content.py +35 -0
  192. capo_codedeploy/types/application_id.py +5 -0
  193. capo_codedeploy/types/application_info.py +90 -0
  194. capo_codedeploy/types/application_name.py +5 -0
  195. capo_codedeploy/types/application_revision_sort_by.py +18 -0
  196. capo_codedeploy/types/applications_info_list.py +33 -0
  197. capo_codedeploy/types/applications_list.py +19 -0
  198. capo_codedeploy/types/arn.py +5 -0
  199. capo_codedeploy/types/auto_rollback_configuration.py +50 -0
  200. capo_codedeploy/types/auto_rollback_event.py +18 -0
  201. capo_codedeploy/types/auto_rollback_events_list.py +35 -0
  202. capo_codedeploy/types/auto_scaling_group.py +47 -0
  203. capo_codedeploy/types/auto_scaling_group_hook.py +5 -0
  204. capo_codedeploy/types/auto_scaling_group_list.py +35 -0
  205. capo_codedeploy/types/auto_scaling_group_name.py +5 -0
  206. capo_codedeploy/types/auto_scaling_group_name_list.py +19 -0
  207. capo_codedeploy/types/batch_get_application_revisions_input.py +55 -0
  208. capo_codedeploy/types/batch_get_application_revisions_output.py +56 -0
  209. capo_codedeploy/types/batch_get_applications_input.py +45 -0
  210. capo_codedeploy/types/batch_get_applications_output.py +42 -0
  211. capo_codedeploy/types/batch_get_deployment_groups_input.py +57 -0
  212. capo_codedeploy/types/batch_get_deployment_groups_output.py +49 -0
  213. capo_codedeploy/types/batch_get_deployment_instances_input.py +53 -0
  214. capo_codedeploy/types/batch_get_deployment_instances_output.py +49 -0
  215. capo_codedeploy/types/batch_get_deployment_targets_input.py +51 -0
  216. capo_codedeploy/types/batch_get_deployment_targets_output.py +42 -0
  217. capo_codedeploy/types/batch_get_deployments_input.py +43 -0
  218. capo_codedeploy/types/batch_get_deployments_output.py +42 -0
  219. capo_codedeploy/types/batch_get_on_premises_instances_input.py +45 -0
  220. capo_codedeploy/types/batch_get_on_premises_instances_output.py +42 -0
  221. capo_codedeploy/types/blue_green_deployment_configuration.py +84 -0
  222. capo_codedeploy/types/blue_instance_termination_option.py +46 -0
  223. capo_codedeploy/types/boolean.py +5 -0
  224. capo_codedeploy/types/bundle_type.py +20 -0
  225. capo_codedeploy/types/cloud_formation_resource_type.py +5 -0
  226. capo_codedeploy/types/cloud_formation_target.py +112 -0
  227. capo_codedeploy/types/commit_id.py +5 -0
  228. capo_codedeploy/types/compute_platform.py +18 -0
  229. capo_codedeploy/types/continue_deployment_input.py +49 -0
  230. capo_codedeploy/types/create_application_input.py +67 -0
  231. capo_codedeploy/types/create_application_output.py +28 -0
  232. capo_codedeploy/types/create_deployment_config_input.py +115 -0
  233. capo_codedeploy/types/create_deployment_config_output.py +30 -0
  234. capo_codedeploy/types/create_deployment_group_input.py +353 -0
  235. capo_codedeploy/types/create_deployment_group_output.py +30 -0
  236. capo_codedeploy/types/create_deployment_input.py +178 -0
  237. capo_codedeploy/types/create_deployment_output.py +28 -0
  238. capo_codedeploy/types/delete_application_input.py +31 -0
  239. capo_codedeploy/types/delete_deployment_config_input.py +35 -0
  240. capo_codedeploy/types/delete_deployment_group_input.py +45 -0
  241. capo_codedeploy/types/delete_deployment_group_output.py +42 -0
  242. capo_codedeploy/types/delete_git_hub_account_token_input.py +30 -0
  243. capo_codedeploy/types/delete_git_hub_account_token_output.py +30 -0
  244. capo_codedeploy/types/delete_resources_by_external_id_input.py +28 -0
  245. capo_codedeploy/types/delete_resources_by_external_id_output.py +18 -0
  246. capo_codedeploy/types/deployment_config_id.py +5 -0
  247. capo_codedeploy/types/deployment_config_info.py +134 -0
  248. capo_codedeploy/types/deployment_config_name.py +5 -0
  249. capo_codedeploy/types/deployment_configs_list.py +19 -0
  250. capo_codedeploy/types/deployment_creator.py +23 -0
  251. capo_codedeploy/types/deployment_group_id.py +5 -0
  252. capo_codedeploy/types/deployment_group_info.py +420 -0
  253. capo_codedeploy/types/deployment_group_info_list.py +35 -0
  254. capo_codedeploy/types/deployment_group_name.py +5 -0
  255. capo_codedeploy/types/deployment_groups_list.py +19 -0
  256. capo_codedeploy/types/deployment_id.py +5 -0
  257. capo_codedeploy/types/deployment_info.py +499 -0
  258. capo_codedeploy/types/deployment_option.py +17 -0
  259. capo_codedeploy/types/deployment_overview.py +64 -0
  260. capo_codedeploy/types/deployment_ready_action.py +17 -0
  261. capo_codedeploy/types/deployment_ready_option.py +50 -0
  262. capo_codedeploy/types/deployment_status.py +23 -0
  263. capo_codedeploy/types/deployment_status_list.py +33 -0
  264. capo_codedeploy/types/deployment_status_message_list.py +19 -0
  265. capo_codedeploy/types/deployment_style.py +61 -0
  266. capo_codedeploy/types/deployment_target.py +115 -0
  267. capo_codedeploy/types/deployment_target_list.py +33 -0
  268. capo_codedeploy/types/deployment_target_type.py +19 -0
  269. capo_codedeploy/types/deployment_type.py +17 -0
  270. capo_codedeploy/types/deployment_wait_type.py +17 -0
  271. capo_codedeploy/types/deployments_info_list.py +31 -0
  272. capo_codedeploy/types/deployments_list.py +17 -0
  273. capo_codedeploy/types/deregister_on_premises_instance_input.py +33 -0
  274. capo_codedeploy/types/description.py +5 -0
  275. capo_codedeploy/types/diagnostics.py +63 -0
  276. capo_codedeploy/types/duration.py +5 -0
  277. capo_codedeploy/types/e_tag.py +5 -0
  278. capo_codedeploy/types/ec2_tag_filter.py +52 -0
  279. capo_codedeploy/types/ec2_tag_filter_list.py +29 -0
  280. capo_codedeploy/types/ec2_tag_filter_type.py +18 -0
  281. capo_codedeploy/types/ec2_tag_set.py +42 -0
  282. capo_codedeploy/types/ec2_tag_set_list.py +35 -0
  283. capo_codedeploy/types/ecs_cluster_name.py +5 -0
  284. capo_codedeploy/types/ecs_service.py +35 -0
  285. capo_codedeploy/types/ecs_service_list.py +29 -0
  286. capo_codedeploy/types/ecs_service_name.py +5 -0
  287. capo_codedeploy/types/ecs_target.py +114 -0
  288. capo_codedeploy/types/ecs_task_set.py +111 -0
  289. capo_codedeploy/types/ecs_task_set_count.py +5 -0
  290. capo_codedeploy/types/ecs_task_set_identifier.py +5 -0
  291. capo_codedeploy/types/ecs_task_set_list.py +29 -0
  292. capo_codedeploy/types/ecs_task_set_status.py +5 -0
  293. capo_codedeploy/types/elb_info.py +28 -0
  294. capo_codedeploy/types/elb_info_list.py +29 -0
  295. capo_codedeploy/types/elb_name.py +5 -0
  296. capo_codedeploy/types/error_code.py +49 -0
  297. capo_codedeploy/types/error_information.py +43 -0
  298. capo_codedeploy/types/error_message.py +5 -0
  299. capo_codedeploy/types/external_id.py +5 -0
  300. capo_codedeploy/types/file_exists_behavior.py +18 -0
  301. capo_codedeploy/types/filter_value.py +5 -0
  302. capo_codedeploy/types/filter_value_list.py +17 -0
  303. capo_codedeploy/types/generic_revision_info.py +96 -0
  304. capo_codedeploy/types/get_application_input.py +31 -0
  305. capo_codedeploy/types/get_application_output.py +40 -0
  306. capo_codedeploy/types/get_application_revision_input.py +51 -0
  307. capo_codedeploy/types/get_application_revision_output.py +70 -0
  308. capo_codedeploy/types/get_deployment_config_input.py +35 -0
  309. capo_codedeploy/types/get_deployment_config_output.py +42 -0
  310. capo_codedeploy/types/get_deployment_group_input.py +43 -0
  311. capo_codedeploy/types/get_deployment_group_output.py +42 -0
  312. capo_codedeploy/types/get_deployment_input.py +31 -0
  313. capo_codedeploy/types/get_deployment_instance_input.py +39 -0
  314. capo_codedeploy/types/get_deployment_instance_output.py +42 -0
  315. capo_codedeploy/types/get_deployment_output.py +40 -0
  316. capo_codedeploy/types/get_deployment_target_input.py +39 -0
  317. capo_codedeploy/types/get_deployment_target_output.py +42 -0
  318. capo_codedeploy/types/get_on_premises_instance_input.py +31 -0
  319. capo_codedeploy/types/get_on_premises_instance_output.py +40 -0
  320. capo_codedeploy/types/git_hub_account_token_name.py +5 -0
  321. capo_codedeploy/types/git_hub_account_token_name_list.py +19 -0
  322. capo_codedeploy/types/git_hub_location.py +35 -0
  323. capo_codedeploy/types/green_fleet_provisioning_action.py +17 -0
  324. capo_codedeploy/types/green_fleet_provisioning_option.py +42 -0
  325. capo_codedeploy/types/iam_session_arn.py +5 -0
  326. capo_codedeploy/types/iam_user_arn.py +5 -0
  327. capo_codedeploy/types/instance_action.py +17 -0
  328. capo_codedeploy/types/instance_arn.py +5 -0
  329. capo_codedeploy/types/instance_count.py +5 -0
  330. capo_codedeploy/types/instance_id.py +5 -0
  331. capo_codedeploy/types/instance_info.py +95 -0
  332. capo_codedeploy/types/instance_info_list.py +29 -0
  333. capo_codedeploy/types/instance_name.py +5 -0
  334. capo_codedeploy/types/instance_name_list.py +17 -0
  335. capo_codedeploy/types/instance_status.py +22 -0
  336. capo_codedeploy/types/instance_status_list.py +31 -0
  337. capo_codedeploy/types/instance_summary.py +107 -0
  338. capo_codedeploy/types/instance_summary_list.py +33 -0
  339. capo_codedeploy/types/instance_target.py +112 -0
  340. capo_codedeploy/types/instance_type.py +17 -0
  341. capo_codedeploy/types/instance_type_list.py +29 -0
  342. capo_codedeploy/types/instances_list.py +17 -0
  343. capo_codedeploy/types/key.py +5 -0
  344. capo_codedeploy/types/lambda_function_alias.py +5 -0
  345. capo_codedeploy/types/lambda_function_info.py +69 -0
  346. capo_codedeploy/types/lambda_function_name.py +5 -0
  347. capo_codedeploy/types/lambda_target.py +114 -0
  348. capo_codedeploy/types/last_deployment_info.py +74 -0
  349. capo_codedeploy/types/lifecycle_error_code.py +21 -0
  350. capo_codedeploy/types/lifecycle_event.py +95 -0
  351. capo_codedeploy/types/lifecycle_event_hook_execution_id.py +5 -0
  352. capo_codedeploy/types/lifecycle_event_list.py +31 -0
  353. capo_codedeploy/types/lifecycle_event_name.py +5 -0
  354. capo_codedeploy/types/lifecycle_event_status.py +21 -0
  355. capo_codedeploy/types/lifecycle_message.py +5 -0
  356. capo_codedeploy/types/list_application_revisions_input.py +111 -0
  357. capo_codedeploy/types/list_application_revisions_output.py +49 -0
  358. capo_codedeploy/types/list_applications_input.py +28 -0
  359. capo_codedeploy/types/list_applications_output.py +49 -0
  360. capo_codedeploy/types/list_deployment_configs_input.py +28 -0
  361. capo_codedeploy/types/list_deployment_configs_output.py +49 -0
  362. capo_codedeploy/types/list_deployment_groups_input.py +40 -0
  363. capo_codedeploy/types/list_deployment_groups_output.py +58 -0
  364. capo_codedeploy/types/list_deployment_instances_input.py +82 -0
  365. capo_codedeploy/types/list_deployment_instances_output.py +47 -0
  366. capo_codedeploy/types/list_deployment_targets_input.py +57 -0
  367. capo_codedeploy/types/list_deployment_targets_output.py +45 -0
  368. capo_codedeploy/types/list_deployments_input.py +93 -0
  369. capo_codedeploy/types/list_deployments_output.py +47 -0
  370. capo_codedeploy/types/list_git_hub_account_token_names_input.py +28 -0
  371. capo_codedeploy/types/list_git_hub_account_token_names_output.py +49 -0
  372. capo_codedeploy/types/list_on_premises_instances_input.py +68 -0
  373. capo_codedeploy/types/list_on_premises_instances_output.py +49 -0
  374. capo_codedeploy/types/list_state_filter_action.py +18 -0
  375. capo_codedeploy/types/list_tags_for_resource_input.py +38 -0
  376. capo_codedeploy/types/list_tags_for_resource_output.py +43 -0
  377. capo_codedeploy/types/listener_arn.py +5 -0
  378. capo_codedeploy/types/listener_arn_list.py +17 -0
  379. capo_codedeploy/types/load_balancer_info.py +80 -0
  380. capo_codedeploy/types/log_tail.py +5 -0
  381. capo_codedeploy/types/message.py +5 -0
  382. capo_codedeploy/types/minimum_healthy_hosts.py +50 -0
  383. capo_codedeploy/types/minimum_healthy_hosts_per_zone.py +50 -0
  384. capo_codedeploy/types/minimum_healthy_hosts_per_zone_type.py +17 -0
  385. capo_codedeploy/types/minimum_healthy_hosts_per_zone_value.py +5 -0
  386. capo_codedeploy/types/minimum_healthy_hosts_type.py +17 -0
  387. capo_codedeploy/types/minimum_healthy_hosts_value.py +5 -0
  388. capo_codedeploy/types/next_token.py +5 -0
  389. capo_codedeploy/types/nullable_boolean.py +5 -0
  390. capo_codedeploy/types/on_premises_tag_set.py +42 -0
  391. capo_codedeploy/types/on_premises_tag_set_list.py +31 -0
  392. capo_codedeploy/types/outdated_instances_strategy.py +17 -0
  393. capo_codedeploy/types/percentage.py +5 -0
  394. capo_codedeploy/types/put_lifecycle_event_hook_execution_status_input.py +60 -0
  395. capo_codedeploy/types/put_lifecycle_event_hook_execution_status_output.py +32 -0
  396. capo_codedeploy/types/raw_string.py +35 -0
  397. capo_codedeploy/types/raw_string_content.py +5 -0
  398. capo_codedeploy/types/raw_string_sha256.py +5 -0
  399. capo_codedeploy/types/register_application_revision_input.py +58 -0
  400. capo_codedeploy/types/register_on_premises_instance_input.py +47 -0
  401. capo_codedeploy/types/registration_status.py +17 -0
  402. capo_codedeploy/types/related_deployments.py +55 -0
  403. capo_codedeploy/types/remove_tags_from_on_premises_instances_input.py +61 -0
  404. capo_codedeploy/types/repository.py +5 -0
  405. capo_codedeploy/types/revision_info.py +63 -0
  406. capo_codedeploy/types/revision_info_list.py +29 -0
  407. capo_codedeploy/types/revision_location.py +114 -0
  408. capo_codedeploy/types/revision_location_list.py +33 -0
  409. capo_codedeploy/types/revision_location_type.py +19 -0
  410. capo_codedeploy/types/role.py +5 -0
  411. capo_codedeploy/types/rollback_info.py +49 -0
  412. capo_codedeploy/types/s3_bucket.py +5 -0
  413. capo_codedeploy/types/s3_key.py +5 -0
  414. capo_codedeploy/types/s3_location.py +64 -0
  415. capo_codedeploy/types/script_name.py +5 -0
  416. capo_codedeploy/types/skip_wait_time_for_instance_termination_input.py +28 -0
  417. capo_codedeploy/types/sort_order.py +17 -0
  418. capo_codedeploy/types/stop_deployment_input.py +40 -0
  419. capo_codedeploy/types/stop_deployment_output.py +43 -0
  420. capo_codedeploy/types/stop_status.py +17 -0
  421. capo_codedeploy/types/tag.py +35 -0
  422. capo_codedeploy/types/tag_filter.py +50 -0
  423. capo_codedeploy/types/tag_filter_list.py +29 -0
  424. capo_codedeploy/types/tag_filter_type.py +18 -0
  425. capo_codedeploy/types/tag_key_list.py +17 -0
  426. capo_codedeploy/types/tag_list.py +29 -0
  427. capo_codedeploy/types/tag_resource_input.py +45 -0
  428. capo_codedeploy/types/tag_resource_output.py +18 -0
  429. capo_codedeploy/types/target_arn.py +5 -0
  430. capo_codedeploy/types/target_filter_name.py +17 -0
  431. capo_codedeploy/types/target_filters.py +40 -0
  432. capo_codedeploy/types/target_group_info.py +28 -0
  433. capo_codedeploy/types/target_group_info_list.py +33 -0
  434. capo_codedeploy/types/target_group_name.py +5 -0
  435. capo_codedeploy/types/target_group_pair_info.py +79 -0
  436. capo_codedeploy/types/target_group_pair_info_list.py +35 -0
  437. capo_codedeploy/types/target_id.py +5 -0
  438. capo_codedeploy/types/target_id_list.py +17 -0
  439. capo_codedeploy/types/target_instances.py +78 -0
  440. capo_codedeploy/types/target_label.py +17 -0
  441. capo_codedeploy/types/target_status.py +22 -0
  442. capo_codedeploy/types/time.py +20 -0
  443. capo_codedeploy/types/time_based_canary.py +37 -0
  444. capo_codedeploy/types/time_based_linear.py +37 -0
  445. capo_codedeploy/types/time_range.py +50 -0
  446. capo_codedeploy/types/timestamp.py +20 -0
  447. capo_codedeploy/types/traffic_route.py +42 -0
  448. capo_codedeploy/types/traffic_routing_config.py +80 -0
  449. capo_codedeploy/types/traffic_routing_type.py +18 -0
  450. capo_codedeploy/types/traffic_weight.py +5 -0
  451. capo_codedeploy/types/trigger_config.py +58 -0
  452. capo_codedeploy/types/trigger_config_list.py +31 -0
  453. capo_codedeploy/types/trigger_event_type.py +25 -0
  454. capo_codedeploy/types/trigger_event_type_list.py +35 -0
  455. capo_codedeploy/types/trigger_name.py +5 -0
  456. capo_codedeploy/types/trigger_target_arn.py +5 -0
  457. capo_codedeploy/types/untag_resource_input.py +47 -0
  458. capo_codedeploy/types/untag_resource_output.py +18 -0
  459. capo_codedeploy/types/update_application_input.py +38 -0
  460. capo_codedeploy/types/update_deployment_group_input.py +343 -0
  461. capo_codedeploy/types/update_deployment_group_output.py +42 -0
  462. capo_codedeploy/types/value.py +5 -0
  463. capo_codedeploy/types/version.py +5 -0
  464. capo_codedeploy/types/version_id.py +5 -0
  465. capo_codedeploy/types/wait_time_in_mins.py +5 -0
  466. capo_codedeploy/types/wait_time_in_seconds.py +5 -0
  467. capo_codedeploy/types/zonal_config.py +63 -0
  468. capo_codedeploy-0.1.0.dist-info/METADATA +102 -0
  469. capo_codedeploy-0.1.0.dist-info/RECORD +472 -0
  470. capo_codedeploy-0.1.0.dist-info/WHEEL +5 -0
  471. capo_codedeploy-0.1.0.dist-info/licenses/LICENSE +21 -0
  472. capo_codedeploy-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,389 @@
1
+ """Endpoint rule-set runtime — hand-written helpers shared by every generated
2
+ ``_endpoint_rule_set.py``. Pure, no third-party deps.
3
+
4
+ Functions mirror the Smithy rules-engine standard library:
5
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+ from collections.abc import Mapping
12
+ from dataclasses import dataclass, field
13
+ from typing import Any, TypedDict
14
+ from urllib.parse import quote, urlsplit
15
+
16
+
17
+ @dataclass(frozen=True, slots=True)
18
+ class Endpoint:
19
+ """Resolved endpoint returned by ``resolve()``.
20
+
21
+ Mirrors the rules-engine *Endpoint object*: a ``url`` plus optional
22
+ ``properties`` (arbitrary document values) and ``headers`` (multi-value
23
+ map of header name to list of values).
24
+
25
+ Reference:
26
+ https://smithy.io/2.0/additional-specs/rules-engine/specification.html#endpoint-object
27
+ """
28
+
29
+ url: str
30
+ properties: dict[str, Any] = field(default_factory=dict)
31
+ headers: dict[str, list[str]] = field(default_factory=dict)
32
+
33
+
34
+ class EndpointError(Exception):
35
+ """Raised when no endpoint rule matches or an ``error`` rule fires.
36
+
37
+ Corresponds to the rules-engine *error rule*: terminates evaluation
38
+ with a diagnostic message produced by the rule set.
39
+
40
+ Reference:
41
+ https://smithy.io/2.0/additional-specs/rules-engine/specification.html#error-rule
42
+ """
43
+
44
+
45
+ _PLACEHOLDER = re.compile(r"\{([A-Za-z_][A-Za-z0-9_]*)(?:#([A-Za-z0-9_.\[\]]+))?\}")
46
+
47
+
48
+ def interpolate(template: str, params: object, locals_: dict[str, Any]) -> str:
49
+ """Expand a rules-engine *template string*.
50
+
51
+ Substitutes ``{Name}`` and ``{Name#path.subpath}`` references inside
52
+ ``template``. Names resolve against ``locals_`` first (variables bound
53
+ by ``assign`` conditions), then against ``params`` attributes (any
54
+ object with attribute access — a dataclass, plain class, etc.; not a
55
+ dict).
56
+ ``#path`` segments walk the resolved value via :func:`get_attr`.
57
+
58
+ Raises :class:`EndpointError` if a referenced name resolves to ``None``.
59
+
60
+ Reference:
61
+ https://smithy.io/2.0/additional-specs/rules-engine/specification.html#template-strings
62
+ """
63
+
64
+ def replace(match: re.Match[str]) -> str:
65
+ name, path = match.group(1), match.group(2)
66
+
67
+ if name in locals_:
68
+ value = locals_[name]
69
+ elif hasattr(params, name):
70
+ value = getattr(params, name)
71
+ else:
72
+ raise EndpointError(f"interpolate: unknown reference '{name}'")
73
+
74
+ if value is None:
75
+ raise EndpointError(f"interpolate: '{name}' is None")
76
+
77
+ if path:
78
+ value = get_attr(value, path)
79
+
80
+ if value is None:
81
+ raise EndpointError(f"interpolate: '{name}#{path}' is None")
82
+
83
+ if isinstance(value, bool):
84
+ return "true" if value else "false"
85
+ return str(value)
86
+
87
+ return _PLACEHOLDER.sub(replace, template)
88
+
89
+
90
+ _SEGMENT_RE = re.compile(r"([A-Za-z_][A-Za-z0-9_]*|\[-?\d+\])")
91
+
92
+
93
+ def get_attr(value: Mapping[str, object] | list[str], path: str) -> object:
94
+ """Rules-engine ``getAttr`` — index into a value by a dotted/bracketed path.
95
+
96
+ Walks segments like ``a.b[0].c`` against dicts (key lookup), objects
97
+ (attribute lookup), and indexable sequences (integer index). Any missing
98
+ key, missing attribute, out-of-range index, or non-indexable cursor
99
+ short-circuits to ``None``.
100
+
101
+ Reference:
102
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html#getattr-function
103
+ """
104
+ cursor: object = value
105
+ for segment in _SEGMENT_RE.findall(path):
106
+ if cursor is None:
107
+ return None
108
+
109
+ if segment.startswith("["):
110
+ # Array index
111
+ idx = int(segment[1:-1])
112
+ try:
113
+ cursor = cursor[idx] # type: ignore
114
+ except IndexError:
115
+ return None
116
+ except TypeError:
117
+ return None
118
+ except KeyError:
119
+ return None
120
+ else:
121
+ # Field access
122
+ if isinstance(cursor, dict):
123
+ cursor = cursor.get(segment)
124
+ else:
125
+ cursor = getattr(cursor, segment, None)
126
+
127
+ return cursor
128
+
129
+
130
+ def string_equals(a: Any, b: Any) -> bool:
131
+ """Rules-engine ``stringEquals`` — strict string equality.
132
+
133
+ Both operands must be Python ``str``; any non-str comparand returns
134
+ ``False``.
135
+
136
+ Reference:
137
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html#stringequals-function
138
+ """
139
+ return isinstance(a, str) and isinstance(b, str) and a == b
140
+
141
+
142
+ _HOST_LABEL = re.compile(r"^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?$")
143
+
144
+
145
+ def substring(value: Any, start: int, stop: int, reverse: bool) -> str | None:
146
+ """Rules-engine ``substring`` — slice an ASCII string by ``[start, stop)``.
147
+
148
+ Returns ``None`` when ``value`` is not a string, contains non-ASCII
149
+ code points, or the ``start``/``stop`` indices are negative, equal,
150
+ inverted, or past the end. When ``reverse`` is true, indices count
151
+ from the end of the string toward the start.
152
+
153
+ Reference:
154
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html#substring-function
155
+ """
156
+ if not isinstance(value, str):
157
+ return None
158
+ if not value.isascii():
159
+ return None
160
+ if start < 0 or stop < 0 or start >= stop:
161
+ return None
162
+ if stop > len(value):
163
+ return None
164
+ if reverse:
165
+ n = len(value)
166
+ return value[n - stop : n - start]
167
+ return value[start:stop]
168
+
169
+
170
+ def is_valid_host_label(value: Any, allow_subdomains: bool) -> bool:
171
+ """Rules-engine ``isValidHostLabel`` — validate an RFC 1123 host label.
172
+
173
+ A label is 1–63 chars of ``[A-Za-z0-9-]`` that does not start or end
174
+ with a hyphen. When ``allow_subdomains`` is true, ``value`` may be a
175
+ dot-separated sequence of such labels (every label must be valid).
176
+
177
+ Reference:
178
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html#isvalidhostlabel-function
179
+ """
180
+ if not isinstance(value, str) or not value:
181
+ return False
182
+ if allow_subdomains:
183
+ labels = value.split(".")
184
+ return bool(labels) and all(_HOST_LABEL.match(label) for label in labels)
185
+ return _HOST_LABEL.match(value) is not None
186
+
187
+
188
+ def uri_encode(value: str | None) -> str:
189
+ """Rules-engine ``uriEncode`` — percent-encode per RFC 3986 §2.3.
190
+
191
+ Every character outside the unreserved set ``A-Z a-z 0-9 - _ . ~`` is
192
+ percent-encoded, including ``/``. Non-string input yields ``""``.
193
+
194
+ Reference:
195
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html#uriencode-function
196
+ """
197
+ if value is None:
198
+ return ""
199
+ return quote(value, safe="-_.~")
200
+
201
+
202
+ class ParsedUrl(TypedDict):
203
+ scheme: str
204
+ authority: str
205
+ path: str
206
+ normalizedPath: str
207
+ isIp: bool
208
+
209
+
210
+ def parse_url(value: str) -> ParsedUrl | None:
211
+ """Rules-engine ``parseUrl`` — split an HTTP(S) URL into components.
212
+
213
+ Returns a :class:`ParsedUrl` with ``scheme``, ``authority`` (host plus
214
+ optional ``:port``), ``path``, ``normalizedPath`` (``path`` guaranteed
215
+ to end in ``/``), and ``isIp`` (true for IPv4 dotted-quad or IPv6
216
+ hosts). Returns ``None`` when ``value`` is not a string, the scheme is
217
+ not ``http``/``https``, or a query/fragment is present.
218
+
219
+ Reference:
220
+ https://smithy.io/2.0/additional-specs/rules-engine/standard-library.html#parseurl-function
221
+ """
222
+
223
+ try:
224
+ parts = urlsplit(value)
225
+
226
+ if parts.scheme not in ("http", "https"):
227
+ return None
228
+
229
+ # Smithy parseUrl rejects query strings and fragments.
230
+ if parts.query or parts.fragment:
231
+ return None
232
+
233
+ # urlsplit preserves the raw/encoded path.
234
+ path = parts.path
235
+
236
+ normalized_path = path if path.endswith("/") else f"{path}/"
237
+
238
+ return {
239
+ "scheme": parts.scheme,
240
+ "authority": parts.netloc,
241
+ "path": path,
242
+ "normalizedPath": normalized_path,
243
+ "isIp": _looks_like_ip(parts.hostname or ""),
244
+ }
245
+
246
+ except Exception:
247
+ return None
248
+
249
+
250
+ def _looks_like_ip(host: str) -> bool:
251
+ if not host:
252
+ return False
253
+ if ":" in host: # IPv6 (urlsplit strips brackets from hostname)
254
+ return True
255
+ parts = host.split(".")
256
+ return len(parts) == 4 and all(p.isdigit() for p in parts)
257
+
258
+
259
+ class ParsedArn(TypedDict):
260
+ partition: str
261
+ service: str
262
+ region: str
263
+ accountId: str
264
+ resourceId: list[str]
265
+
266
+
267
+ def aws_parse_arn(arn: Any) -> ParsedArn | None:
268
+ """AWS rules-engine ``aws.parseArn`` — split an ARN into components.
269
+
270
+ An ARN has the shape ``arn:<partition>:<service>:<region>:<account>:<resource>``.
271
+ Returns a :class:`ParsedArn` with ``partition``, ``service``, ``region``,
272
+ ``accountId``, and ``resourceId`` (the trailing resource section split
273
+ on ``:`` and ``/``). Returns ``None`` when ``arn`` is not a string, has
274
+ fewer than six ``:``-separated parts, does not begin with ``arn``, or
275
+ has empty ``partition``/``service``/resource sections. ``region`` and
276
+ ``accountId`` may be empty (e.g. IAM ARNs have no region).
277
+
278
+ Reference:
279
+ https://smithy.io/2.0/aws/rules-engine/standard-library.html#aws-parsearn-function
280
+ """
281
+ if not isinstance(arn, str):
282
+ return None
283
+ parts = arn.split(":", 5)
284
+ if len(parts) != 6:
285
+ return None
286
+ prefix, partition, service, region, account_id, resource = parts
287
+ if prefix != "arn" or not partition or not service or not resource:
288
+ return None
289
+ return {
290
+ "partition": partition,
291
+ "service": service,
292
+ "region": region,
293
+ "accountId": account_id,
294
+ "resourceId": re.split(r"[:/]", resource),
295
+ }
296
+
297
+
298
+ _S3_BUCKET_LABEL = re.compile(r"^[a-z0-9][a-z0-9\-]{1,61}[a-z0-9]$")
299
+ _IPV4 = re.compile(r"^(\d{1,3}\.){3}\d{1,3}$")
300
+
301
+
302
+ def aws_is_virtual_hostable_s3_bucket(value: Any, allow_subdomains: Any) -> bool:
303
+ """AWS rules-engine ``aws.isVirtualHostableS3Bucket`` — validate an S3
304
+ bucket name for virtual-hosted-style addressing.
305
+
306
+ Returns ``True`` when ``value`` is a DNS-compliant S3 bucket name
307
+ (3–63 chars, lowercase alphanumeric plus hyphens, no leading/trailing
308
+ hyphen, no IPv4-address shape). When ``allow_subdomains`` is true,
309
+ dotted bucket names are accepted and each dot-separated label must
310
+ independently satisfy the same rules.
311
+
312
+ Reference:
313
+ https://smithy.io/2.0/aws/rules-engine/standard-library.html#aws-isvirtualhostables3bucket-function
314
+ """
315
+ if not isinstance(value, str):
316
+ return False
317
+ if allow_subdomains:
318
+ labels = value.split(".")
319
+ return all(aws_is_virtual_hostable_s3_bucket(label, False) for label in labels)
320
+ if _IPV4.match(value):
321
+ return False
322
+ return _S3_BUCKET_LABEL.match(value) is not None
323
+
324
+
325
+ def apply_label(url: str, placeholder: str, value: str) -> str:
326
+ """Substitute ``placeholder`` in ``url`` with ``value`` — except when the
327
+ rule engine has already embedded ``value`` as a whole host label or path
328
+ segment. In that case, strip the placeholder and collapse any resulting
329
+ ``//`` or trailing ``/`` in the path.
330
+
331
+ "Part" = host label (split on ``.``) or path segment (split on ``/``).
332
+ Match is case-sensitive, whole-part only. An empty ``value`` always
333
+ substitutes (never matches).
334
+ """
335
+ if placeholder not in url:
336
+ return url
337
+
338
+ if not value:
339
+ return url.replace(placeholder, "")
340
+
341
+ try:
342
+ parsed = urlsplit(url)
343
+ # urlsplit.hostname lowercases the value, which would break the
344
+ # case-sensitive membership test below. Extract from netloc manually
345
+ # to preserve the original casing.
346
+ netloc = parsed.netloc or ""
347
+ host = (
348
+ netloc.rsplit(":", 1)[0]
349
+ if ":" in netloc and not netloc.startswith("[")
350
+ else netloc
351
+ )
352
+ path = parsed.path or ""
353
+ except Exception:
354
+ # Parse failure -> fall back to substitution (defensive).
355
+ return url.replace(placeholder, quote(value, safe=""))
356
+
357
+ host_labels = host.split(".") if host and not host.startswith("[") else []
358
+ path_segments = [seg for seg in path.split("/") if seg]
359
+
360
+ # Guard: only strip when the placeholder is in the path portion. If the
361
+ # placeholder appears only in a query string or fragment, a coincidental
362
+ # host/path match must not trigger the strip branch.
363
+ scheme_sep = url.find("://")
364
+ head_end = url.find("/", scheme_sep + 3) if scheme_sep != -1 else -1
365
+ path_portion = url[head_end:] if head_end != -1 else ""
366
+ # Strip query and fragment off the path portion for the placeholder check.
367
+ for sep in ("?", "#"):
368
+ idx = path_portion.find(sep)
369
+ if idx != -1:
370
+ path_portion = path_portion[:idx]
371
+ if placeholder not in path_portion:
372
+ return url.replace(placeholder, quote(value, safe=""))
373
+
374
+ if value in host_labels or value in path_segments:
375
+ # Splice the placeholder out, then collapse the one seam slash our
376
+ # removal may have created. Pre-existing slash duplicates in the
377
+ # URI template are not our concern — we only fix what we caused.
378
+ idx = url.find(placeholder)
379
+ stripped = url[:idx] + url[idx + len(placeholder) :]
380
+ before = stripped[idx - 1] if idx > 0 else ""
381
+ after = stripped[idx] if idx < len(stripped) else ""
382
+ if before == "/" and after == "/":
383
+ stripped = stripped[:idx] + stripped[idx + 1 :]
384
+ # Placeholder at the path's tail leaves a stray trailing ``/``.
385
+ if stripped.endswith("/"):
386
+ stripped = stripped[:-1]
387
+ return stripped
388
+
389
+ return url.replace(placeholder, quote(value, safe=""))
@@ -0,0 +1,160 @@
1
+ from __future__ import annotations
2
+
3
+ import configparser
4
+ import functools
5
+ import os
6
+ from dataclasses import dataclass
7
+ from pathlib import Path
8
+ from typing import TypeVar
9
+
10
+ from capo_codedeploy._services._pipeline import (
11
+ AsyncInterceptor,
12
+ AsyncNextFn,
13
+ AsyncOperationRequest,
14
+ AsyncOperationResponse,
15
+ Interceptor,
16
+ NextFn,
17
+ OperationRequest,
18
+ OperationResponse,
19
+ )
20
+
21
+ ENDPOINT_ENV_VAR = "AWS_ENDPOINT_URL_CODE_DEPLOY"
22
+ SERVICE_ID = "code_deploy"
23
+ TInput = TypeVar("TInput")
24
+ TOutput = TypeVar("TOutput")
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class AwsSettings:
29
+ region: str | None
30
+ endpoint: str | None
31
+ use_fips: bool
32
+ use_dual_stack: bool
33
+ max_attempts: int
34
+
35
+
36
+ def _env_bool(name: str) -> bool | None:
37
+ val = os.environ.get(name)
38
+ if val is None:
39
+ return None
40
+ return val.strip().lower() in ("true", "1")
41
+
42
+
43
+ def _profile_bool(section: dict[str, str], key: str) -> bool | None:
44
+ val = section.get(key)
45
+ if val is None:
46
+ return None
47
+ return val.strip().lower() in ("true", "1")
48
+
49
+
50
+ def config_file() -> Path:
51
+ raw_cfg = os.environ.get("AWS_CONFIG_FILE")
52
+ return Path(raw_cfg).expanduser() if raw_cfg else Path.home() / ".aws" / "config"
53
+
54
+
55
+ def active_profile() -> str:
56
+ return (
57
+ os.environ.get("AWS_PROFILE")
58
+ or os.environ.get("AWS_DEFAULT_PROFILE")
59
+ or "default"
60
+ )
61
+
62
+
63
+ def _load_profile(
64
+ profile: str | None = None,
65
+ ) -> tuple[dict[str, str], dict[str, dict[str, str]]]:
66
+ profile = profile or active_profile()
67
+ cfg_file = config_file()
68
+ merged: dict[str, str] = {}
69
+ services: dict[str, dict[str, str]] = {}
70
+ if cfg_file.is_file():
71
+ cfg = configparser.ConfigParser(interpolation=None)
72
+ cfg.read(cfg_file)
73
+ key = "default" if profile == "default" else f"profile {profile}"
74
+ if cfg.has_section(key):
75
+ merged.update(dict(cfg.items(key)))
76
+ services_name = merged.get("services")
77
+ if services_name and cfg.has_section(f"services {services_name}"):
78
+ raw = dict(cfg.items(f"services {services_name}"))
79
+ for svc, block in raw.items():
80
+ parsed: dict[str, str] = {}
81
+ for line in block.splitlines():
82
+ stripped = line.strip()
83
+ if "=" in stripped:
84
+ k, _, val = stripped.partition("=")
85
+ parsed[k.strip()] = val.strip()
86
+ services[svc] = parsed
87
+ return merged, services
88
+
89
+
90
+ @functools.cache
91
+ def load_aws_settings() -> AwsSettings:
92
+ profile, services = _load_profile()
93
+ region = os.environ.get("AWS_REGION") or profile.get("region")
94
+ endpoint = (
95
+ os.environ.get(ENDPOINT_ENV_VAR)
96
+ or os.environ.get("AWS_ENDPOINT_URL")
97
+ or services.get(SERVICE_ID, {}).get("endpoint_url")
98
+ or profile.get("endpoint_url")
99
+ )
100
+ use_fips: bool | None = _env_bool("AWS_USE_FIPS_ENDPOINT")
101
+ if use_fips is None:
102
+ use_fips = _profile_bool(profile, "use_fips_endpoint")
103
+ if use_fips is None:
104
+ use_fips = False
105
+ use_dual_stack: bool | None = _env_bool("AWS_USE_DUALSTACK_ENDPOINT")
106
+ if use_dual_stack is None:
107
+ use_dual_stack = _profile_bool(profile, "use_dualstack_endpoint")
108
+ if use_dual_stack is None:
109
+ use_dual_stack = False
110
+ max_attempts_raw = os.environ.get("AWS_MAX_ATTEMPTS") or profile.get("max_attempts")
111
+ max_attempts = int(max_attempts_raw) if max_attempts_raw else 3
112
+ return AwsSettings(
113
+ region=region,
114
+ endpoint=endpoint,
115
+ use_fips=use_fips,
116
+ use_dual_stack=use_dual_stack,
117
+ max_attempts=max_attempts,
118
+ )
119
+
120
+
121
+ def aws_config() -> Interceptor[TInput, TOutput]:
122
+ def interceptor(
123
+ request: OperationRequest[TInput], next: NextFn[TInput, TOutput]
124
+ ) -> OperationResponse[TOutput]:
125
+ settings = load_aws_settings()
126
+ options = request.options
127
+ if options.region is None:
128
+ options.region = settings.region
129
+ if options.endpoint is None:
130
+ options.endpoint = settings.endpoint
131
+ if options.use_fips is None:
132
+ options.use_fips = settings.use_fips
133
+ if options.use_dual_stack is None:
134
+ options.use_dual_stack = settings.use_dual_stack
135
+ if options.retry_max_attempts is None:
136
+ options.retry_max_attempts = settings.max_attempts
137
+ return next(request)
138
+
139
+ return interceptor
140
+
141
+
142
+ def aaws_config() -> AsyncInterceptor[TInput, TOutput]:
143
+ async def interceptor(
144
+ request: AsyncOperationRequest[TInput], next: AsyncNextFn[TInput, TOutput]
145
+ ) -> AsyncOperationResponse[TOutput]:
146
+ settings = load_aws_settings()
147
+ options = request.options
148
+ if options.region is None:
149
+ options.region = settings.region
150
+ if options.endpoint is None:
151
+ options.endpoint = settings.endpoint
152
+ if options.use_fips is None:
153
+ options.use_fips = settings.use_fips
154
+ if options.use_dual_stack is None:
155
+ options.use_dual_stack = settings.use_dual_stack
156
+ if options.retry_max_attempts is None:
157
+ options.retry_max_attempts = settings.max_attempts
158
+ return await next(request)
159
+
160
+ return interceptor