runbooks 0.2.3__py3-none-any.whl → 0.6.1__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 (221) hide show
  1. conftest.py +26 -0
  2. jupyter-agent/.env.template +2 -0
  3. jupyter-agent/.gitattributes +35 -0
  4. jupyter-agent/README.md +16 -0
  5. jupyter-agent/app.py +256 -0
  6. jupyter-agent/cloudops-agent.png +0 -0
  7. jupyter-agent/ds-system-prompt.txt +154 -0
  8. jupyter-agent/jupyter-agent.png +0 -0
  9. jupyter-agent/llama3_template.jinja +123 -0
  10. jupyter-agent/requirements.txt +9 -0
  11. jupyter-agent/utils.py +409 -0
  12. runbooks/__init__.py +71 -3
  13. runbooks/__main__.py +13 -0
  14. runbooks/aws/ec2_describe_instances.py +1 -1
  15. runbooks/aws/ec2_run_instances.py +8 -2
  16. runbooks/aws/ec2_start_stop_instances.py +17 -4
  17. runbooks/aws/ec2_unused_volumes.py +5 -1
  18. runbooks/aws/s3_create_bucket.py +4 -2
  19. runbooks/aws/s3_list_objects.py +6 -1
  20. runbooks/aws/tagging_lambda_handler.py +13 -2
  21. runbooks/aws/tags.json +12 -0
  22. runbooks/base.py +353 -0
  23. runbooks/cfat/README.md +49 -0
  24. runbooks/cfat/__init__.py +74 -0
  25. runbooks/cfat/app.ts +644 -0
  26. runbooks/cfat/assessment/__init__.py +40 -0
  27. runbooks/cfat/assessment/asana-import.csv +39 -0
  28. runbooks/cfat/assessment/cfat-checks.csv +31 -0
  29. runbooks/cfat/assessment/cfat.txt +520 -0
  30. runbooks/cfat/assessment/collectors.py +200 -0
  31. runbooks/cfat/assessment/jira-import.csv +39 -0
  32. runbooks/cfat/assessment/runner.py +387 -0
  33. runbooks/cfat/assessment/validators.py +290 -0
  34. runbooks/cfat/cli.py +103 -0
  35. runbooks/cfat/docs/asana-import.csv +24 -0
  36. runbooks/cfat/docs/cfat-checks.csv +31 -0
  37. runbooks/cfat/docs/cfat.txt +335 -0
  38. runbooks/cfat/docs/checks-output.png +0 -0
  39. runbooks/cfat/docs/cloudshell-console-run.png +0 -0
  40. runbooks/cfat/docs/cloudshell-download.png +0 -0
  41. runbooks/cfat/docs/cloudshell-output.png +0 -0
  42. runbooks/cfat/docs/downloadfile.png +0 -0
  43. runbooks/cfat/docs/jira-import.csv +24 -0
  44. runbooks/cfat/docs/open-cloudshell.png +0 -0
  45. runbooks/cfat/docs/report-header.png +0 -0
  46. runbooks/cfat/models.py +1026 -0
  47. runbooks/cfat/package-lock.json +5116 -0
  48. runbooks/cfat/package.json +38 -0
  49. runbooks/cfat/report.py +496 -0
  50. runbooks/cfat/reporting/__init__.py +46 -0
  51. runbooks/cfat/reporting/exporters.py +337 -0
  52. runbooks/cfat/reporting/formatters.py +496 -0
  53. runbooks/cfat/reporting/templates.py +135 -0
  54. runbooks/cfat/run-assessment.sh +23 -0
  55. runbooks/cfat/runner.py +69 -0
  56. runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
  57. runbooks/cfat/src/actions/check-config-existence.ts +37 -0
  58. runbooks/cfat/src/actions/check-control-tower.ts +37 -0
  59. runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
  60. runbooks/cfat/src/actions/check-iam-users.ts +50 -0
  61. runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
  62. runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
  63. runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
  64. runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
  65. runbooks/cfat/src/actions/create-backlog.ts +372 -0
  66. runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
  67. runbooks/cfat/src/actions/create-report.ts +616 -0
  68. runbooks/cfat/src/actions/define-account-type.ts +51 -0
  69. runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
  70. runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
  71. runbooks/cfat/src/actions/get-idc-info.ts +34 -0
  72. runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
  73. runbooks/cfat/src/actions/get-org-details.ts +35 -0
  74. runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
  75. runbooks/cfat/src/actions/get-org-ous.ts +35 -0
  76. runbooks/cfat/src/actions/get-regions.ts +22 -0
  77. runbooks/cfat/src/actions/zip-assessment.ts +27 -0
  78. runbooks/cfat/src/types/index.d.ts +147 -0
  79. runbooks/cfat/tests/__init__.py +141 -0
  80. runbooks/cfat/tests/test_cli.py +340 -0
  81. runbooks/cfat/tests/test_integration.py +290 -0
  82. runbooks/cfat/tests/test_models.py +505 -0
  83. runbooks/cfat/tests/test_reporting.py +354 -0
  84. runbooks/cfat/tsconfig.json +16 -0
  85. runbooks/cfat/webpack.config.cjs +27 -0
  86. runbooks/config.py +260 -0
  87. runbooks/finops/__init__.py +88 -0
  88. runbooks/finops/aws_client.py +245 -0
  89. runbooks/finops/cli.py +151 -0
  90. runbooks/finops/cost_processor.py +410 -0
  91. runbooks/finops/dashboard_runner.py +448 -0
  92. runbooks/finops/helpers.py +355 -0
  93. runbooks/finops/main.py +14 -0
  94. runbooks/finops/profile_processor.py +174 -0
  95. runbooks/finops/types.py +66 -0
  96. runbooks/finops/visualisations.py +80 -0
  97. runbooks/inventory/.gitignore +354 -0
  98. runbooks/inventory/ArgumentsClass.py +261 -0
  99. runbooks/inventory/Inventory_Modules.py +6130 -0
  100. runbooks/inventory/LandingZone/delete_lz.py +1075 -0
  101. runbooks/inventory/README.md +1320 -0
  102. runbooks/inventory/__init__.py +62 -0
  103. runbooks/inventory/account_class.py +532 -0
  104. runbooks/inventory/all_my_instances_wrapper.py +123 -0
  105. runbooks/inventory/aws_decorators.py +201 -0
  106. runbooks/inventory/cfn_move_stack_instances.py +1526 -0
  107. runbooks/inventory/check_cloudtrail_compliance.py +614 -0
  108. runbooks/inventory/check_controltower_readiness.py +1107 -0
  109. runbooks/inventory/check_landingzone_readiness.py +711 -0
  110. runbooks/inventory/cloudtrail.md +727 -0
  111. runbooks/inventory/collectors/__init__.py +20 -0
  112. runbooks/inventory/collectors/aws_compute.py +518 -0
  113. runbooks/inventory/collectors/aws_networking.py +275 -0
  114. runbooks/inventory/collectors/base.py +222 -0
  115. runbooks/inventory/core/__init__.py +19 -0
  116. runbooks/inventory/core/collector.py +303 -0
  117. runbooks/inventory/core/formatter.py +296 -0
  118. runbooks/inventory/delete_s3_buckets_objects.py +169 -0
  119. runbooks/inventory/discovery.md +81 -0
  120. runbooks/inventory/draw_org_structure.py +748 -0
  121. runbooks/inventory/ec2_vpc_utils.py +341 -0
  122. runbooks/inventory/find_cfn_drift_detection.py +272 -0
  123. runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
  124. runbooks/inventory/find_cfn_stackset_drift.py +733 -0
  125. runbooks/inventory/find_ec2_security_groups.py +669 -0
  126. runbooks/inventory/find_landingzone_versions.py +201 -0
  127. runbooks/inventory/find_vpc_flow_logs.py +1221 -0
  128. runbooks/inventory/inventory.sh +659 -0
  129. runbooks/inventory/list_cfn_stacks.py +558 -0
  130. runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
  131. runbooks/inventory/list_cfn_stackset_operations.py +734 -0
  132. runbooks/inventory/list_cfn_stacksets.py +453 -0
  133. runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
  134. runbooks/inventory/list_ds_directories.py +354 -0
  135. runbooks/inventory/list_ec2_availability_zones.py +286 -0
  136. runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
  137. runbooks/inventory/list_ec2_instances.py +425 -0
  138. runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
  139. runbooks/inventory/list_elbs_load_balancers.py +411 -0
  140. runbooks/inventory/list_enis_network_interfaces.py +526 -0
  141. runbooks/inventory/list_guardduty_detectors.py +568 -0
  142. runbooks/inventory/list_iam_policies.py +404 -0
  143. runbooks/inventory/list_iam_roles.py +518 -0
  144. runbooks/inventory/list_iam_saml_providers.py +359 -0
  145. runbooks/inventory/list_lambda_functions.py +882 -0
  146. runbooks/inventory/list_org_accounts.py +446 -0
  147. runbooks/inventory/list_org_accounts_users.py +354 -0
  148. runbooks/inventory/list_rds_db_instances.py +406 -0
  149. runbooks/inventory/list_route53_hosted_zones.py +318 -0
  150. runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
  151. runbooks/inventory/list_sns_topics.py +360 -0
  152. runbooks/inventory/list_ssm_parameters.py +402 -0
  153. runbooks/inventory/list_vpc_subnets.py +433 -0
  154. runbooks/inventory/list_vpcs.py +422 -0
  155. runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
  156. runbooks/inventory/models/__init__.py +24 -0
  157. runbooks/inventory/models/account.py +192 -0
  158. runbooks/inventory/models/inventory.py +309 -0
  159. runbooks/inventory/models/resource.py +247 -0
  160. runbooks/inventory/recover_cfn_stack_ids.py +205 -0
  161. runbooks/inventory/requirements.txt +12 -0
  162. runbooks/inventory/run_on_multi_accounts.py +211 -0
  163. runbooks/inventory/tests/common_test_data.py +3661 -0
  164. runbooks/inventory/tests/common_test_functions.py +204 -0
  165. runbooks/inventory/tests/script_test_data.py +0 -0
  166. runbooks/inventory/tests/setup.py +24 -0
  167. runbooks/inventory/tests/src.py +18 -0
  168. runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
  169. runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
  170. runbooks/inventory/tests/test_inventory_modules.py +55 -0
  171. runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
  172. runbooks/inventory/tests/test_moto_integration_example.py +273 -0
  173. runbooks/inventory/tests/test_org_list_accounts.py +49 -0
  174. runbooks/inventory/update_aws_actions.py +173 -0
  175. runbooks/inventory/update_cfn_stacksets.py +1215 -0
  176. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
  177. runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
  178. runbooks/inventory/update_s3_public_access_block.py +539 -0
  179. runbooks/inventory/utils/__init__.py +23 -0
  180. runbooks/inventory/utils/aws_helpers.py +510 -0
  181. runbooks/inventory/utils/threading_utils.py +493 -0
  182. runbooks/inventory/utils/validation.py +682 -0
  183. runbooks/inventory/verify_ec2_security_groups.py +1430 -0
  184. runbooks/main.py +785 -0
  185. runbooks/organizations/__init__.py +12 -0
  186. runbooks/organizations/manager.py +374 -0
  187. runbooks/security_baseline/README.md +324 -0
  188. runbooks/security_baseline/checklist/alternate_contacts.py +8 -1
  189. runbooks/security_baseline/checklist/bucket_public_access.py +4 -1
  190. runbooks/security_baseline/checklist/cloudwatch_alarm_configuration.py +9 -2
  191. runbooks/security_baseline/checklist/guardduty_enabled.py +9 -2
  192. runbooks/security_baseline/checklist/multi_region_instance_usage.py +5 -1
  193. runbooks/security_baseline/checklist/root_access_key.py +6 -1
  194. runbooks/security_baseline/config-origin.json +1 -1
  195. runbooks/security_baseline/config.json +1 -1
  196. runbooks/security_baseline/permission.json +1 -1
  197. runbooks/security_baseline/report_generator.py +10 -2
  198. runbooks/security_baseline/report_template_en.html +8 -8
  199. runbooks/security_baseline/report_template_jp.html +8 -8
  200. runbooks/security_baseline/report_template_kr.html +13 -13
  201. runbooks/security_baseline/report_template_vn.html +8 -8
  202. runbooks/security_baseline/requirements.txt +7 -0
  203. runbooks/security_baseline/run_script.py +8 -2
  204. runbooks/security_baseline/security_baseline_tester.py +10 -2
  205. runbooks/security_baseline/utils/common.py +5 -1
  206. runbooks/utils/__init__.py +204 -0
  207. runbooks-0.6.1.dist-info/METADATA +373 -0
  208. runbooks-0.6.1.dist-info/RECORD +237 -0
  209. {runbooks-0.2.3.dist-info → runbooks-0.6.1.dist-info}/WHEEL +1 -1
  210. runbooks-0.6.1.dist-info/entry_points.txt +7 -0
  211. runbooks-0.6.1.dist-info/licenses/LICENSE +201 -0
  212. runbooks-0.6.1.dist-info/top_level.txt +3 -0
  213. runbooks/python101/calculator.py +0 -34
  214. runbooks/python101/config.py +0 -1
  215. runbooks/python101/exceptions.py +0 -16
  216. runbooks/python101/file_manager.py +0 -218
  217. runbooks/python101/toolkit.py +0 -153
  218. runbooks-0.2.3.dist-info/METADATA +0 -435
  219. runbooks-0.2.3.dist-info/RECORD +0 -61
  220. runbooks-0.2.3.dist-info/entry_points.txt +0 -3
  221. runbooks-0.2.3.dist-info/top_level.txt +0 -1
@@ -0,0 +1,734 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ AWS CloudFormation StackSet Operations Discovery and Analysis Script
5
+
6
+ This enterprise-grade inventory and monitoring script provides comprehensive StackSet operations
7
+ discovery, analysis, and tracking across multi-account AWS Organizations environments. Designed
8
+ for infrastructure teams, DevOps engineers, and cloud architects managing large-scale CloudFormation
9
+ StackSet deployments with centralized operational oversight and deployment orchestration.
10
+
11
+ Key Features:
12
+ - StackSet operations discovery and lifecycle tracking across organizational accounts
13
+ - Multi-threaded StackSet instance enumeration for deployment topology analysis
14
+ - Last operation status analysis with failure detection and operational insights
15
+ - Stack instance detailed status tracking for deployment troubleshooting
16
+ - Fragment-based filtering for targeted StackSet operations analysis and monitoring
17
+ - Comprehensive error handling for authorization, throttling, and connectivity issues
18
+ - Progress tracking with real-time operational feedback and performance metrics
19
+ - Flexible output formatting with CSV export for reporting and integration
20
+
21
+ Authentication and Access:
22
+ - Single-profile authentication for centralized StackSet management operations
23
+ - Support for AWS Organizations cross-account role-based access patterns
24
+ - Regional validation and access control for StackSet operational boundaries
25
+ - Comprehensive error handling for authentication and authorization failures
26
+
27
+ Enterprise Use Cases:
28
+ - Centralized StackSet deployment monitoring and operational excellence
29
+ - Infrastructure governance and compliance tracking for organizational standards
30
+ - Deployment failure analysis and troubleshooting for operational support
31
+ - StackSet lifecycle management and capacity planning across accounts
32
+ - Operational dashboards and reporting for infrastructure management teams
33
+
34
+ Performance and Scalability:
35
+ - Multi-threaded architecture for efficient StackSet instance discovery
36
+ - Queue-based worker pattern for concurrent StackSet operations analysis
37
+ - Optimized AWS API usage with progress tracking and performance timing
38
+ - Configurable concurrency limits for API rate limiting and throttling management
39
+
40
+ Security Considerations:
41
+ - Read-only operations ensuring no accidental StackSet modifications
42
+ - Comprehensive audit logging for compliance and operational tracking
43
+ - Secure credential handling with profile-based authentication
44
+ - Access validation and error handling for enterprise security requirements
45
+
46
+ Dependencies:
47
+ - boto3: AWS SDK for CloudFormation StackSet operations
48
+ - colorama: Enhanced terminal output with color coding
49
+ - tqdm: Progress bars for long-running discovery operations
50
+ - Inventory_Modules: Custom AWS inventory and discovery utilities
51
+ - ArgumentsClass: Standardized CLI argument parsing and validation
52
+ - account_class: AWS account access and credential management
53
+
54
+ Example Usage:
55
+ # Basic StackSet operations discovery
56
+ python list_cfn_stackset_operations.py --profile production
57
+
58
+ # Fragment-based operations analysis
59
+ python list_cfn_stackset_operations.py --fragment SecurityBaseline
60
+
61
+ # Detailed instance enumeration with timing
62
+ python list_cfn_stackset_operations.py --instances --timing
63
+
64
+ Output:
65
+ Displays discovered StackSet operations with last operation status, failure counts,
66
+ completion timestamps, and deployment topology insights for operational monitoring.
67
+ """
68
+
69
+ import logging
70
+ import os
71
+ import sys
72
+ from queue import Queue
73
+ from threading import Thread
74
+ from time import time
75
+
76
+ import Inventory_Modules
77
+ from account_class import aws_acct_access
78
+ from ArgumentsClass import CommonArguments
79
+ from botocore.exceptions import ClientError
80
+ from colorama import Fore, init
81
+ from Inventory_Modules import display_results, find_stacksets3, get_regions3
82
+ from tqdm.auto import tqdm
83
+
84
+ init()
85
+
86
+ __version__ = "2024.05.18"
87
+ ERASE_LINE = "\x1b[2K"
88
+ begin_time = time()
89
+ DefaultMaxWorkerThreads = 5
90
+
91
+
92
+ ##################
93
+ # Functions
94
+ ##################
95
+ def parse_args(args: object):
96
+ """
97
+ Parse and validate CLI arguments for StackSet operations discovery and analysis.
98
+
99
+ Configures comprehensive argument parsing for StackSet operations inventory across
100
+ AWS Organizations with support for fragment-based filtering, instance enumeration,
101
+ status tracking, and operational analysis. Provides enterprise-grade CLI interface
102
+ for infrastructure teams managing large-scale StackSet deployments.
103
+
104
+ Args:
105
+ args (object): Command-line arguments list for parsing and validation
106
+
107
+ Returns:
108
+ argparse.Namespace: Parsed arguments object containing:
109
+ - Profile: AWS profile for StackSet management operations access
110
+ - Region: Target AWS region for StackSet operations discovery
111
+ - Fragments: StackSet name fragments for targeted search and filtering
112
+ - Exact: Boolean flag for exact fragment matching vs. substring matching
113
+ - RootOnly: Boolean flag to limit discovery to root account only
114
+ - Timing: Boolean flag to enable performance timing and metrics
115
+ - Verbosity: Logging level for operational visibility and debugging
116
+ - pinstancecount: Boolean flag for StackSet instance enumeration
117
+ - pstatus: StackSet status filter ('Active' or 'Deleted')
118
+ - Filename: Optional output file path for CSV export and reporting
119
+
120
+ CLI Arguments:
121
+ Single Profile Authentication:
122
+ - --profile: AWS profile for centralized StackSet management access
123
+ - Single-profile mode for focused operational analysis
124
+
125
+ Regional Configuration:
126
+ - --region: Target AWS region for StackSet operations discovery
127
+ - Single-region mode for focused operational boundaries
128
+
129
+ StackSet Filtering:
130
+ - --fragment: StackSet name fragments for targeted operations analysis
131
+ - --exact: Enable exact fragment matching for precise filtering
132
+ - --status: Filter by StackSet status (Active/Deleted) for lifecycle tracking
133
+
134
+ Instance Analysis:
135
+ - --instances: Enable StackSet instance enumeration for topology analysis
136
+ - Provides deployment pattern insights and capacity planning data
137
+
138
+ Operational Controls:
139
+ - --root-only: Limit discovery to root account StackSet operations
140
+ - --timing: Enable performance timing for operational metrics
141
+ - --save-to-file: Export results to CSV for reporting and integration
142
+ - --verbose: Control logging verbosity for debugging and audit trails
143
+
144
+ Enterprise Features:
145
+ - Standardized CLI interface consistent with inventory tooling
146
+ - Fragment-based search for targeted StackSet operations analysis
147
+ - Instance enumeration for deployment topology and capacity insights
148
+ - Status filtering for StackSet lifecycle and operational tracking
149
+ - Output formatting with CSV export for enterprise reporting
150
+
151
+ Validation and Error Handling:
152
+ - Argument validation with informative error messages
153
+ - Help text generation for operational documentation
154
+ - Version information for tooling compatibility tracking
155
+ - Default value configuration for operational convenience
156
+ """
157
+ script_path, script_name = os.path.split(sys.argv[0])
158
+ parser = CommonArguments()
159
+
160
+ # Configure standardized CLI arguments for enterprise inventory operations
161
+ parser.singleprofile() # Single AWS profile for centralized StackSet management access
162
+ parser.singleregion() # Single region specification for focused operational boundaries
163
+ parser.fragment() # Fragment-based filtering for targeted StackSet operations analysis
164
+ parser.extendedargs() # Extended argument support for advanced filtering capabilities
165
+ parser.save_to_file() # CSV export functionality for enterprise reporting and integration
166
+ parser.rootOnly() # Root account only mode for organizational StackSet oversight
167
+ parser.timing() # Performance timing metrics for operational analysis
168
+ parser.verbosity() # Configurable logging verbosity for debugging and audit trails
169
+ parser.version(__version__) # Version information for tooling compatibility tracking
170
+
171
+ # Add script-specific arguments for StackSet operations analysis
172
+ local = parser.my_parser.add_argument_group(script_name, "Parameters specific to this script")
173
+ local.add_argument(
174
+ "-i",
175
+ "--instances",
176
+ dest="pinstancecount",
177
+ action="store_true",
178
+ default=False,
179
+ help="Enable StackSet instance enumeration for deployment topology analysis and capacity planning",
180
+ )
181
+ local.add_argument(
182
+ "-s",
183
+ "--status",
184
+ dest="pstatus",
185
+ metavar="CloudFormation status",
186
+ default="Active",
187
+ choices=["active", "ACTIVE", "Active", "deleted", "DELETED", "Deleted"],
188
+ help="Filter StackSets by lifecycle status - 'ACTIVE' for operational StackSets or 'DELETED' for cleanup analysis",
189
+ )
190
+ return parser.my_parser.parse_args(args)
191
+
192
+
193
+ def setup_auth_and_regions(
194
+ fProfile: str, fRegion: str = None, fStackFrag: list = None, fExact: bool = False
195
+ ) -> (aws_acct_access, list):
196
+ """
197
+ Initialize authentication and configure regional access for StackSet operations discovery.
198
+
199
+ Establishes AWS authentication context and validates regional configuration for StackSet
200
+ operations analysis and monitoring. Performs single-region validation and provides
201
+ operational context display for infrastructure teams managing centralized StackSet
202
+ deployments across AWS Organizations environments.
203
+
204
+ Args:
205
+ fProfile (str): AWS profile name for authentication and StackSet management access
206
+ If None, uses default profile or credential chain
207
+ fRegion (str): Target AWS region for StackSet operations discovery
208
+ Defaults to 'us-east-1' if not specified
209
+ fStackFrag (list): StackSet name fragments for targeted search and filtering
210
+ Defaults to ['all'] for comprehensive discovery
211
+ fExact (bool): Enable exact fragment matching for precise filtering
212
+ Default False for substring-based matching
213
+
214
+ Returns:
215
+ tuple: Two-element tuple containing:
216
+ - aws_acct_access: Authenticated account access object for StackSet operations
217
+ - list: Validated AWS regions list for StackSet discovery operations
218
+
219
+ Authentication and Validation:
220
+ - Establishes AWS authentication using the specified profile
221
+ - Validates single-region configuration for focused operational boundaries
222
+ - Performs regional access validation for StackSet management operations
223
+ - Handles authentication failures with appropriate error messaging
224
+
225
+ Regional Configuration:
226
+ - Single-region mode for focused StackSet operations analysis
227
+ - Regional validation to ensure StackSet management capabilities
228
+ - Error handling for invalid or inaccessible regions
229
+ - Operational context display for transparency and troubleshooting
230
+
231
+ Operational Display:
232
+ - Account type and number identification for organizational context
233
+ - Regional scope confirmation for operational boundaries
234
+ - Fragment matching configuration display for search transparency
235
+ - Clear operational intent communication for infrastructure teams
236
+
237
+ Error Handling:
238
+ - Connection error detection with appropriate system exit
239
+ - Profile validation and authentication failure management
240
+ - Regional access validation with informative error messages
241
+ - Comprehensive error logging for troubleshooting and audit trails
242
+
243
+ Enterprise Features:
244
+ - Single-region focus for targeted StackSet operations monitoring
245
+ - Clear operational scope display for infrastructure governance
246
+ - Fragment-based search configuration for operational efficiency
247
+ - Account type awareness for organizational structure recognition
248
+ """
249
+
250
+ # Set default values for optional parameters to ensure consistent operation
251
+ if fStackFrag is None:
252
+ fStackfrag = ["all"] # Default to comprehensive StackSet discovery
253
+ if fRegion is None:
254
+ fRegion = "us-east-1" # Default to primary AWS region for StackSet management
255
+
256
+ try:
257
+ # Establish AWS authentication using the specified profile
258
+ aws_acct = aws_acct_access(fProfile)
259
+ except ConnectionError as my_Error:
260
+ # Handle authentication and connection failures with appropriate logging
261
+ logging.error(f"Exiting due to error: {my_Error}")
262
+ sys.exit(8)
263
+
264
+ # Validate regional access and availability for StackSet operations
265
+ RegionList = get_regions3(aws_acct, [fRegion])
266
+
267
+ # Enforce single-region constraint for focused StackSet operations analysis
268
+ if fRegion.lower() not in RegionList:
269
+ print()
270
+ print(
271
+ f"{Fore.RED}You specified '{fRegion}' as the region, but this script only works with a single region.\n"
272
+ f"Please run the command again and specify only a single, valid region{Fore.RESET}"
273
+ )
274
+ print()
275
+ raise ValueError(f"You specified '{fRegion}' as the region, but this script only works with a single region.")
276
+
277
+ # Display operational scope and configuration for transparency
278
+ print()
279
+ action = "but not modify" # Read-only operations for safety
280
+ print(f"You asked me to find ({action}) stacksets that match the following:")
281
+ print(f"\t\tIn the {aws_acct.AccountType} account {aws_acct.acct_number}")
282
+ print(f"\t\tIn this Region: {fRegion}")
283
+
284
+ # Display fragment matching configuration for search transparency
285
+ if fExact:
286
+ print(f"\t\tFor stacksets that {Fore.RED}exactly match{Fore.RESET} these fragments: {fStackfrag}")
287
+ else:
288
+ print(f"\t\tFor stacksets that contains these fragments: {fStackfrag}")
289
+
290
+ print()
291
+ return aws_acct, RegionList
292
+
293
+
294
+ def collect_cfnstacksets(faws_acct: aws_acct_access, fRegion: str) -> (dict, dict, dict):
295
+ """
296
+ Collect and aggregate StackSet information with comprehensive instance enumeration and analysis.
297
+
298
+ Performs comprehensive StackSet discovery, instance enumeration, and metadata aggregation
299
+ for operational analysis and infrastructure governance. Orchestrates StackSet collection
300
+ with detailed instance topology mapping and account/region distribution analysis for
301
+ enterprise infrastructure teams managing large-scale CloudFormation deployments.
302
+
303
+ Args:
304
+ faws_acct (aws_acct_access): Authenticated AWS account access object for StackSet operations
305
+ fRegion (str): Target AWS region for StackSet discovery and instance enumeration
306
+
307
+ Returns:
308
+ tuple: Three-element tuple containing comprehensive StackSet information:
309
+ dict: StackSet aggregation containing:
310
+ - combined_stack_set_instances: Complete list of StackSet instances with metadata
311
+ - StackSets: Raw StackSet discovery results from inventory modules
312
+ - StackSetsList: Filtered list of StackSet names in operational scope
313
+ dict: Account aggregation containing:
314
+ - AccountList: Unique list of accounts with StackSet instances
315
+ dict: Region aggregation containing:
316
+ - FoundRegionList: Unique list of regions with StackSet deployments
317
+
318
+ StackSet Discovery Process:
319
+ - Fragment-based StackSet discovery using inventory modules
320
+ - Comprehensive instance enumeration across organizational accounts
321
+ - Account and region filtering based on operational scope
322
+ - Metadata extraction for deployment topology analysis
323
+
324
+ Instance Analysis Features:
325
+ - Multi-threaded instance discovery for performance optimization
326
+ - Account filtering for targeted operational analysis
327
+ - Regional distribution mapping for capacity planning
328
+ - Status tracking and deployment pattern analysis
329
+
330
+ Data Aggregation:
331
+ - Deduplication of accounts and regions for clean reporting
332
+ - StackSet name filtering and scope management
333
+ - Comprehensive metadata preservation for analysis
334
+ - Structured data organization for downstream processing
335
+
336
+ Enterprise Infrastructure Governance:
337
+ - Organizational StackSet visibility and management
338
+ - Deployment topology analysis for operational excellence
339
+ - Account and region distribution insights for capacity planning
340
+ - Infrastructure governance and compliance tracking
341
+
342
+ Error Handling:
343
+ - AWS connection validation with appropriate error messaging
344
+ - Failed discovery detection with comprehensive error reporting
345
+ - Graceful degradation for partial discovery scenarios
346
+ - Comprehensive logging for troubleshooting and audit trails
347
+ """
348
+ # Discover StackSets from the Management Account using fragment-based filtering
349
+ StackSets = find_stacksets3(faws_acct, fRegion, pStackfrag, pExact)
350
+ if not StackSets["Success"]:
351
+ # Handle failed StackSet discovery with comprehensive error messaging
352
+ error_message = (
353
+ "Something went wrong with the AWS connection. Please check the parameters supplied and try again."
354
+ )
355
+ sys.exit(error_message)
356
+ logging.info(f"Found {len(StackSets['StackSets'])} StackSetNames that matched your fragment")
357
+
358
+ # Perform comprehensive StackSet instance enumeration across organizational accounts
359
+ combined_stack_set_instances = find_stack_set_instances(StackSets["StackSets"], fRegion)
360
+
361
+ print(ERASE_LINE)
362
+ logging.info(f"Found {len(combined_stack_set_instances)} stack instances.")
363
+
364
+ # Initialize aggregation lists for account and region distribution analysis
365
+ AccountList = []
366
+ StackSetsList = []
367
+ FoundRegionList = []
368
+
369
+ # Process and filter StackSet instances based on account inclusion criteria
370
+ for _ in range(len(combined_stack_set_instances)):
371
+ if pAccountList is None: # Include all discovered instances when no specific account list provided
372
+ StackSetsList.append(combined_stack_set_instances[_]["StackSetName"])
373
+ AccountList.append(combined_stack_set_instances[_]["ChildAccount"])
374
+ FoundRegionList.append(combined_stack_set_instances[_]["ChildRegion"])
375
+ elif pAccountList is not None:
376
+ # Filter instances to include only those in the specified account list
377
+ if combined_stack_set_instances[_]["ChildAccount"] in pAccountList:
378
+ StackSetsList.append(combined_stack_set_instances[_]["StackSetName"])
379
+ AccountList.append(combined_stack_set_instances[_]["ChildAccount"])
380
+ FoundRegionList.append(combined_stack_set_instances[_]["ChildRegion"])
381
+
382
+ # Deduplicate and sort aggregated lists for clean reporting and analysis
383
+ # Filter out None values that occur when StackSets have no deployed instances
384
+ AccountList = sorted(list(set([item for item in AccountList if item is not None])))
385
+
386
+ # Regional aggregation for deployment topology analysis
387
+ # Note: Regional scope is maintained at StackSet level rather than per-account
388
+ # Future enhancement: Consider per-account regional filtering for granular control
389
+ FoundRegionList = sorted(list(set([item for item in FoundRegionList if item is not None])))
390
+ StackSetsList = sorted(list(set(StackSetsList)))
391
+
392
+ # Structure aggregated data for downstream processing and analysis
393
+ StackSet_Dict = {
394
+ "combined_stack_set_instances": combined_stack_set_instances,
395
+ "StackSets": StackSets,
396
+ "StackSetsList": StackSetsList,
397
+ }
398
+ Account_Dict = {"AccountList": AccountList}
399
+ Region_Dict = {"FoundRegionList": FoundRegionList}
400
+ return StackSet_Dict, Account_Dict, Region_Dict
401
+
402
+
403
+ def find_stack_set_instances(fStackSetNames: list, fRegion: str) -> list:
404
+ """
405
+ Discover and enumerate StackSet instances across organizational accounts using multi-threaded processing.
406
+
407
+ Performs comprehensive StackSet instance discovery using concurrent worker threads for efficient
408
+ enumeration across large-scale CloudFormation StackSet deployments. Provides detailed instance
409
+ metadata extraction, status tracking, and deployment topology analysis for enterprise infrastructure
410
+ teams managing multi-account StackSet orchestration and operational monitoring.
411
+
412
+ Args:
413
+ fStackSetNames (list): List of StackSet names for instance discovery and enumeration
414
+ Reserved keyword 'all' enables comprehensive discovery
415
+ fRegion (str): Target AWS region for StackSet instance discovery operations
416
+
417
+ Returns:
418
+ list: Comprehensive list of StackSet instance dictionaries containing:
419
+ - ParentAccountNumber: Management account hosting the StackSet
420
+ - ChildAccount: Target account where StackSet instance is deployed
421
+ - ChildRegion: Target region for StackSet instance deployment
422
+ - StackStatus: Current deployment status of the StackSet instance
423
+ - DetailedStatus: Detailed operational status for troubleshooting
424
+ - StatusReason: Reason description for failed or problematic deployments
425
+ - OrganizationalUnitId: AWS Organizations OU for organizational structure
426
+ - PermissionModel: StackSet permission model (SELF_MANAGED/SERVICE_MANAGED)
427
+ - StackSetName: Parent StackSet name for instance relationship tracking
428
+
429
+ Multi-threaded Architecture:
430
+ - Queue-based worker pattern for concurrent instance discovery
431
+ - Configurable worker thread pool for performance optimization
432
+ - Progress tracking with real-time operational feedback
433
+ - Graceful error handling for authorization and throttling issues
434
+
435
+ Instance Discovery Features:
436
+ - Comprehensive metadata extraction for operational analysis
437
+ - Account filtering support for targeted instance enumeration
438
+ - Regional validation for deployment boundary enforcement
439
+ - Status tracking for deployment lifecycle management
440
+
441
+ Performance Optimization:
442
+ - Concurrent processing for efficient large-scale discovery
443
+ - Progress bars for operational visibility during long-running operations
444
+ - Worker thread scaling based on StackSet count for optimal performance
445
+ - Queue management for efficient work distribution and completion tracking
446
+
447
+ Enterprise Infrastructure Management:
448
+ - Organizational StackSet instance visibility across accounts
449
+ - Deployment topology mapping for capacity planning and governance
450
+ - Status monitoring for operational excellence and troubleshooting
451
+ - Permission model tracking for security and compliance analysis
452
+
453
+ Error Handling:
454
+ - Authorization failure detection with graceful degradation
455
+ - AWS API throttling management with retry logic
456
+ - Connection error handling with comprehensive logging
457
+ - Partial discovery support for operational resilience
458
+ """
459
+
460
+ class FindStackSets(Thread):
461
+ """
462
+ Multi-threaded worker class for concurrent StackSet instance discovery and enumeration.
463
+
464
+ Implements thread-safe StackSet instance discovery using queue-based work distribution
465
+ for efficient processing of large-scale StackSet deployments across organizational accounts.
466
+ """
467
+
468
+ def __init__(self, queue):
469
+ Thread.__init__(self)
470
+ self.queue = queue
471
+
472
+ def run(self):
473
+ while True:
474
+ # Extract work item from queue with StackSet information and processing context
475
+ c_stacksetname, c_region, c_stackset_info, c_PlaceCount = self.queue.get()
476
+ logging.info(f"De-queued info for stack set name {c_stacksetname}")
477
+
478
+ try:
479
+ # Perform StackSet instance discovery for the current StackSet
480
+ # This is the most time-intensive operation in the discovery process
481
+ logging.info(
482
+ f"{ERASE_LINE}Looking through {c_PlaceCount} of {len(fStackSetNames)} stacksets found with {pStackfrag} string in them"
483
+ )
484
+
485
+ # Call inventory module to discover instances for the current StackSet
486
+ # Note: Empty StackSets (without instances) may be excluded from results
487
+ StackInstances = Inventory_Modules.find_stack_instances3(aws_acct, c_region, c_stacksetname)
488
+ logging.warning(f"Found {len(StackInstances)} Stack Instances within the StackSet {c_stacksetname}")
489
+
490
+ # Process each discovered StackSet instance with metadata extraction
491
+ for StackInstance in StackInstances:
492
+ # Validate StackSet instance deployment status
493
+ if "StackId" not in StackInstance.keys():
494
+ logging.info(
495
+ f"The stack instance found {StackInstance} doesn't have a stackid associated. Which means it's never been deployed and probably OUTDATED"
496
+ )
497
+ pass
498
+
499
+ # Apply account filtering for targeted instance enumeration
500
+ if pAccountList is None or StackInstance["Account"] in pAccountList:
501
+ # Include instance if no account filter specified or account matches filter
502
+ # Supports comprehensive discovery and targeted operational analysis
503
+ logging.debug(f"This is Instance #: {str(StackInstance)}")
504
+ logging.debug(f"This is instance status: {str(StackInstance['Status'])}")
505
+ logging.debug(f"This is ChildAccount: {StackInstance['Account']}")
506
+ logging.debug(f"This is ChildRegion: {StackInstance['Region']}")
507
+
508
+ # Validate regional scope and add instance to results
509
+ if StackInstance["Region"] in RegionList:
510
+ # Aggregate comprehensive instance metadata for analysis
511
+ f_combined_stack_set_instances.append(
512
+ {
513
+ "ParentAccountNumber": aws_acct.acct_number, # Management account hosting StackSet
514
+ "ChildAccount": StackInstance["Account"], # Target deployment account
515
+ "ChildRegion": StackInstance["Region"], # Target deployment region
516
+ "StackStatus": StackInstance["Status"], # Current deployment status
517
+ "DetailedStatus": StackInstance["StackInstanceStatus"]["DetailedStatus"]
518
+ if "DetailedStatus" in StackInstance["StackInstanceStatus"]
519
+ else None, # Detailed status for troubleshooting
520
+ "StatusReason": StackInstance["StatusReason"]
521
+ if "StatusReason" in StackInstance
522
+ else None, # Failure reason for operational analysis
523
+ "OrganizationalUnitId": StackInstance["OrganizationalUnitId"]
524
+ if "OrganizationalUnitId" in StackInstance
525
+ else None, # AWS Organizations OU for structural analysis
526
+ "PermissionModel": c_stackset_info["PermissionModel"]
527
+ if "PermissionModel" in c_stackset_info
528
+ else "SELF_MANAGED", # StackSet permission model for security analysis
529
+ "StackSetName": c_stacksetname, # Parent StackSet name for relationship tracking
530
+ }
531
+ )
532
+ elif not (StackInstance["Account"] in pAccountList):
533
+ # Skip instances that don't match the specified account filter
534
+ # Supports targeted operational analysis for specific accounts
535
+ logging.debug(
536
+ f"Found a stack instance, but the account didn't match {pAccountList}... exiting"
537
+ )
538
+ continue
539
+
540
+ except KeyError as my_Error:
541
+ # Handle missing key errors during instance metadata extraction
542
+ logging.error(f"Account Access failed - trying to access {c_stacksetname}")
543
+ logging.info(f"Actual Error: {my_Error}")
544
+ pass
545
+ except AttributeError as my_Error:
546
+ # Handle attribute errors likely caused by incorrect profile configuration
547
+ logging.error(f"Error: Likely that one of the supplied profiles was wrong")
548
+ logging.info(f"Actual Error: {my_Error}")
549
+ continue
550
+ except ClientError as my_Error:
551
+ # Handle AWS API errors including throttling and authorization failures
552
+ logging.error(f"Error: Likely throttling errors from too much activity")
553
+ logging.info(f"Actual Error: {my_Error}")
554
+ continue
555
+ finally:
556
+ # Complete processing and update progress tracking
557
+ logging.info(
558
+ f"{ERASE_LINE}Finished finding stack instances in stackset {c_stacksetname} in region {c_region} - {c_PlaceCount} / {len(fStackSetNames)}"
559
+ )
560
+ pbar.update() # Update progress bar for operational visibility
561
+ self.queue.task_done() # Mark queue item as completed
562
+
563
+ ###########
564
+
565
+ # Initialize processing context and data structures
566
+ if fRegion is None:
567
+ fRegion = "us-east-1" # Default to primary AWS region for StackSet operations
568
+ checkqueue = Queue() # Queue for work distribution across worker threads
569
+
570
+ f_combined_stack_set_instances = [] # Aggregated results list for all discovered instances
571
+ PlaceCount = 0 # Progress counter for operational visibility
572
+
573
+ # Configure optimal worker thread count based on StackSet count and system limits
574
+ WorkerThreads = min(len(fStackSetNames), DefaultMaxWorkerThreads)
575
+
576
+ # Initialize progress tracking for operational visibility during discovery
577
+ pbar = tqdm(
578
+ desc=f"Finding Stackset instances from {len(fStackSetNames)} stacksets",
579
+ total=len(fStackSetNames),
580
+ unit=" stacksets",
581
+ )
582
+
583
+ # Create and start worker thread pool for concurrent StackSet instance discovery
584
+ for x in range(WorkerThreads):
585
+ worker = FindStackSets(checkqueue)
586
+ # Daemon threads allow main thread exit even if workers are still processing
587
+ worker.daemon = True
588
+ worker.start()
589
+
590
+ # Queue StackSet discovery work items for worker thread processing
591
+ for stacksetname in fStackSetNames:
592
+ logging.debug(f"Beginning to queue data - starting with {stacksetname}")
593
+ try:
594
+ # Queue StackSet information for worker thread processing
595
+ # Note: Tuple structure is critical for proper parameter expansion in worker threads
596
+ PlaceCount += 1
597
+ checkqueue.put((stacksetname, fRegion, stacksetname, PlaceCount))
598
+ except ClientError as my_Error:
599
+ # Handle authorization failures with informative error messaging
600
+ if "AuthFailure" in str(my_Error):
601
+ logging.error(
602
+ f"Authorization Failure accessing stack set {stacksetname['StackSetName']} in {fRegion} region"
603
+ )
604
+ logging.warning(f"It's possible that the region {fRegion} hasn't been opted-into")
605
+ pass
606
+
607
+ # Wait for all worker threads to complete processing
608
+ checkqueue.join()
609
+ pbar.close() # Close progress bar after completion
610
+ return f_combined_stack_set_instances
611
+
612
+
613
+ def find_last_operations(faws_acct: aws_acct_access, fStackSetNames: list):
614
+ """
615
+ Discover and analyze the most recent operations for CloudFormation StackSets.
616
+
617
+ Retrieves the last operation performed on each StackSet for operational monitoring,
618
+ failure analysis, and deployment lifecycle tracking. Provides essential operational
619
+ insights for infrastructure teams managing large-scale StackSet deployments across
620
+ AWS Organizations environments.
621
+
622
+ Args:
623
+ faws_acct (aws_acct_access): Authenticated AWS account access object for StackSet operations
624
+ fStackSetNames (list): List of StackSet names for operation history discovery
625
+
626
+ Returns:
627
+ list: List of StackSet operation dictionaries containing:
628
+ - StackSetName: StackSet identifier for operation correlation
629
+ - Operation: Last operation type (CREATE_STACK_SET, UPDATE_STACK_SET, DELETE_STACK_SET)
630
+ - LatestStatus: Current status of the last operation (SUCCEEDED, FAILED, STOPPED)
631
+ - LatestDate: Completion timestamp for operational timeline analysis
632
+ - Details: Failed stack instances count for troubleshooting and analysis
633
+
634
+ Operation Discovery Features:
635
+ - Latest operation retrieval for each StackSet with comprehensive metadata
636
+ - Operation status tracking for deployment lifecycle monitoring
637
+ - Failure count analysis for operational excellence and troubleshooting
638
+ - Timestamp tracking for deployment pattern analysis and audit trails
639
+
640
+ Operational Monitoring:
641
+ - Progress tracking with real-time feedback during operation discovery
642
+ - Sequential processing for reliable operation history retrieval
643
+ - Comprehensive error handling for authorization and connectivity issues
644
+ - Operation metadata extraction for enterprise infrastructure governance
645
+
646
+ Enterprise Use Cases:
647
+ - Deployment failure analysis and operational troubleshooting
648
+ - StackSet lifecycle monitoring for infrastructure governance
649
+ - Operational dashboards and reporting for infrastructure management
650
+ - Compliance tracking and audit trail generation
651
+
652
+ Error Handling:
653
+ - AWS API error management with graceful degradation
654
+ - Authorization failure detection with appropriate logging
655
+ - Missing operation handling for newly created StackSets
656
+ - Comprehensive error reporting for troubleshooting
657
+ """
658
+ # Initialize CloudFormation client for StackSet operations discovery
659
+ StackSetOps_client = faws_acct.session.client("cloudformation")
660
+ AllStackSetOps = []
661
+
662
+ # Discover last operation for each StackSet with progress tracking
663
+ for stacksetname in tqdm(fStackSetNames, desc="Checking stackset operations"):
664
+ # Retrieve most recent operation for the current StackSet
665
+ StackSetOps = StackSetOps_client.list_stack_set_operations(
666
+ StackSetName=stacksetname, MaxResults=1, CallAs="SELF"
667
+ )["Summaries"]
668
+
669
+ # Extract and aggregate operation metadata for analysis
670
+ AllStackSetOps.append(
671
+ {
672
+ "StackSetName": stacksetname, # StackSet identifier for correlation
673
+ "Operation": StackSetOps[0]["Action"], # Operation type for lifecycle tracking
674
+ "LatestStatus": StackSetOps[0]["Status"], # Current operation status
675
+ "LatestDate": StackSetOps[0]["EndTimestamp"], # Completion timestamp
676
+ "Details": StackSetOps[0]["StatusDetails"]["FailedStackInstancesCount"], # Failure count for analysis
677
+ }
678
+ )
679
+ return AllStackSetOps
680
+
681
+
682
+ ##################
683
+ # Main
684
+ ##################
685
+ if __name__ == "__main__":
686
+ args = parse_args(sys.argv[1:])
687
+
688
+ pProfile = args.Profile
689
+ pRegion = args.Region
690
+ pInstanceCount = args.pinstancecount
691
+ pRootOnly = args.RootOnly
692
+ verbose = args.loglevel
693
+ pTiming = args.Time
694
+ pStackfrag: list = args.Fragments
695
+ pExact: bool = args.Exact
696
+ pAccountList = args.Accounts
697
+ pstatus = args.pstatus
698
+ pFilename = args.Filename
699
+ # Setup logging levels
700
+ logging.basicConfig(level=verbose, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
701
+ logging.getLogger("boto3").setLevel(logging.CRITICAL)
702
+ logging.getLogger("botocore").setLevel(logging.CRITICAL)
703
+ logging.getLogger("s3transfer").setLevel(logging.CRITICAL)
704
+ logging.getLogger("urllib3").setLevel(logging.CRITICAL)
705
+
706
+ display_dict = {
707
+ "StackSetName": {"DisplayOrder": 1, "Heading": "Stackset Name"},
708
+ "Operation": {"DisplayOrder": 2, "Heading": "Action"},
709
+ "LatestStatus": {"DisplayOrder": 3, "Heading": "Last status", "Condition": ["FAILED", "STOPPED"]},
710
+ "LatestDate": {"DisplayOrder": 4, "Heading": "Last completed"},
711
+ "Details": {"DisplayOrder": 5, "Heading": "Failures"},
712
+ }
713
+
714
+ # Setup the aws_acct object
715
+ aws_acct, RegionList = setup_auth_and_regions(pProfile)
716
+ # Collect the stacksets, AccountList and RegionList involved
717
+ StackSets, Accounts, Regions = collect_cfnstacksets(aws_acct, pRegion)
718
+ # Get the last operations from the Stacksets we've found
719
+ StackSets_and_Operations = find_last_operations(aws_acct, StackSets["StackSetsList"])
720
+ # Display what we've found
721
+ sorted_StackSets_and_Operations = sorted(StackSets_and_Operations, key=lambda x: x["LatestDate"], reverse=True)
722
+ display_results(sorted_StackSets_and_Operations, display_dict, None, pFilename)
723
+
724
+ print()
725
+ print(ERASE_LINE)
726
+ print(
727
+ f"{Fore.RED}Found {len(StackSets['StackSetsList'])} Stacksets across {len(Accounts)} accounts across {len(Regions)} regions{Fore.RESET}"
728
+ )
729
+ print()
730
+ if pTiming:
731
+ print(ERASE_LINE)
732
+ print(f"{Fore.GREEN}This script took {time() - begin_time:.2f} seconds{Fore.RESET}")
733
+ print("Thanks for using this script...")
734
+ print()