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.
- conftest.py +26 -0
- jupyter-agent/.env.template +2 -0
- jupyter-agent/.gitattributes +35 -0
- jupyter-agent/README.md +16 -0
- jupyter-agent/app.py +256 -0
- jupyter-agent/cloudops-agent.png +0 -0
- jupyter-agent/ds-system-prompt.txt +154 -0
- jupyter-agent/jupyter-agent.png +0 -0
- jupyter-agent/llama3_template.jinja +123 -0
- jupyter-agent/requirements.txt +9 -0
- jupyter-agent/utils.py +409 -0
- runbooks/__init__.py +71 -3
- runbooks/__main__.py +13 -0
- runbooks/aws/ec2_describe_instances.py +1 -1
- runbooks/aws/ec2_run_instances.py +8 -2
- runbooks/aws/ec2_start_stop_instances.py +17 -4
- runbooks/aws/ec2_unused_volumes.py +5 -1
- runbooks/aws/s3_create_bucket.py +4 -2
- runbooks/aws/s3_list_objects.py +6 -1
- runbooks/aws/tagging_lambda_handler.py +13 -2
- runbooks/aws/tags.json +12 -0
- runbooks/base.py +353 -0
- runbooks/cfat/README.md +49 -0
- runbooks/cfat/__init__.py +74 -0
- runbooks/cfat/app.ts +644 -0
- runbooks/cfat/assessment/__init__.py +40 -0
- runbooks/cfat/assessment/asana-import.csv +39 -0
- runbooks/cfat/assessment/cfat-checks.csv +31 -0
- runbooks/cfat/assessment/cfat.txt +520 -0
- runbooks/cfat/assessment/collectors.py +200 -0
- runbooks/cfat/assessment/jira-import.csv +39 -0
- runbooks/cfat/assessment/runner.py +387 -0
- runbooks/cfat/assessment/validators.py +290 -0
- runbooks/cfat/cli.py +103 -0
- runbooks/cfat/docs/asana-import.csv +24 -0
- runbooks/cfat/docs/cfat-checks.csv +31 -0
- runbooks/cfat/docs/cfat.txt +335 -0
- runbooks/cfat/docs/checks-output.png +0 -0
- runbooks/cfat/docs/cloudshell-console-run.png +0 -0
- runbooks/cfat/docs/cloudshell-download.png +0 -0
- runbooks/cfat/docs/cloudshell-output.png +0 -0
- runbooks/cfat/docs/downloadfile.png +0 -0
- runbooks/cfat/docs/jira-import.csv +24 -0
- runbooks/cfat/docs/open-cloudshell.png +0 -0
- runbooks/cfat/docs/report-header.png +0 -0
- runbooks/cfat/models.py +1026 -0
- runbooks/cfat/package-lock.json +5116 -0
- runbooks/cfat/package.json +38 -0
- runbooks/cfat/report.py +496 -0
- runbooks/cfat/reporting/__init__.py +46 -0
- runbooks/cfat/reporting/exporters.py +337 -0
- runbooks/cfat/reporting/formatters.py +496 -0
- runbooks/cfat/reporting/templates.py +135 -0
- runbooks/cfat/run-assessment.sh +23 -0
- runbooks/cfat/runner.py +69 -0
- runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
- runbooks/cfat/src/actions/check-config-existence.ts +37 -0
- runbooks/cfat/src/actions/check-control-tower.ts +37 -0
- runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
- runbooks/cfat/src/actions/check-iam-users.ts +50 -0
- runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
- runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
- runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
- runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
- runbooks/cfat/src/actions/create-backlog.ts +372 -0
- runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
- runbooks/cfat/src/actions/create-report.ts +616 -0
- runbooks/cfat/src/actions/define-account-type.ts +51 -0
- runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
- runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
- runbooks/cfat/src/actions/get-idc-info.ts +34 -0
- runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
- runbooks/cfat/src/actions/get-org-details.ts +35 -0
- runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
- runbooks/cfat/src/actions/get-org-ous.ts +35 -0
- runbooks/cfat/src/actions/get-regions.ts +22 -0
- runbooks/cfat/src/actions/zip-assessment.ts +27 -0
- runbooks/cfat/src/types/index.d.ts +147 -0
- runbooks/cfat/tests/__init__.py +141 -0
- runbooks/cfat/tests/test_cli.py +340 -0
- runbooks/cfat/tests/test_integration.py +290 -0
- runbooks/cfat/tests/test_models.py +505 -0
- runbooks/cfat/tests/test_reporting.py +354 -0
- runbooks/cfat/tsconfig.json +16 -0
- runbooks/cfat/webpack.config.cjs +27 -0
- runbooks/config.py +260 -0
- runbooks/finops/__init__.py +88 -0
- runbooks/finops/aws_client.py +245 -0
- runbooks/finops/cli.py +151 -0
- runbooks/finops/cost_processor.py +410 -0
- runbooks/finops/dashboard_runner.py +448 -0
- runbooks/finops/helpers.py +355 -0
- runbooks/finops/main.py +14 -0
- runbooks/finops/profile_processor.py +174 -0
- runbooks/finops/types.py +66 -0
- runbooks/finops/visualisations.py +80 -0
- runbooks/inventory/.gitignore +354 -0
- runbooks/inventory/ArgumentsClass.py +261 -0
- runbooks/inventory/Inventory_Modules.py +6130 -0
- runbooks/inventory/LandingZone/delete_lz.py +1075 -0
- runbooks/inventory/README.md +1320 -0
- runbooks/inventory/__init__.py +62 -0
- runbooks/inventory/account_class.py +532 -0
- runbooks/inventory/all_my_instances_wrapper.py +123 -0
- runbooks/inventory/aws_decorators.py +201 -0
- runbooks/inventory/cfn_move_stack_instances.py +1526 -0
- runbooks/inventory/check_cloudtrail_compliance.py +614 -0
- runbooks/inventory/check_controltower_readiness.py +1107 -0
- runbooks/inventory/check_landingzone_readiness.py +711 -0
- runbooks/inventory/cloudtrail.md +727 -0
- runbooks/inventory/collectors/__init__.py +20 -0
- runbooks/inventory/collectors/aws_compute.py +518 -0
- runbooks/inventory/collectors/aws_networking.py +275 -0
- runbooks/inventory/collectors/base.py +222 -0
- runbooks/inventory/core/__init__.py +19 -0
- runbooks/inventory/core/collector.py +303 -0
- runbooks/inventory/core/formatter.py +296 -0
- runbooks/inventory/delete_s3_buckets_objects.py +169 -0
- runbooks/inventory/discovery.md +81 -0
- runbooks/inventory/draw_org_structure.py +748 -0
- runbooks/inventory/ec2_vpc_utils.py +341 -0
- runbooks/inventory/find_cfn_drift_detection.py +272 -0
- runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
- runbooks/inventory/find_cfn_stackset_drift.py +733 -0
- runbooks/inventory/find_ec2_security_groups.py +669 -0
- runbooks/inventory/find_landingzone_versions.py +201 -0
- runbooks/inventory/find_vpc_flow_logs.py +1221 -0
- runbooks/inventory/inventory.sh +659 -0
- runbooks/inventory/list_cfn_stacks.py +558 -0
- runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
- runbooks/inventory/list_cfn_stackset_operations.py +734 -0
- runbooks/inventory/list_cfn_stacksets.py +453 -0
- runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
- runbooks/inventory/list_ds_directories.py +354 -0
- runbooks/inventory/list_ec2_availability_zones.py +286 -0
- runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
- runbooks/inventory/list_ec2_instances.py +425 -0
- runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
- runbooks/inventory/list_elbs_load_balancers.py +411 -0
- runbooks/inventory/list_enis_network_interfaces.py +526 -0
- runbooks/inventory/list_guardduty_detectors.py +568 -0
- runbooks/inventory/list_iam_policies.py +404 -0
- runbooks/inventory/list_iam_roles.py +518 -0
- runbooks/inventory/list_iam_saml_providers.py +359 -0
- runbooks/inventory/list_lambda_functions.py +882 -0
- runbooks/inventory/list_org_accounts.py +446 -0
- runbooks/inventory/list_org_accounts_users.py +354 -0
- runbooks/inventory/list_rds_db_instances.py +406 -0
- runbooks/inventory/list_route53_hosted_zones.py +318 -0
- runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
- runbooks/inventory/list_sns_topics.py +360 -0
- runbooks/inventory/list_ssm_parameters.py +402 -0
- runbooks/inventory/list_vpc_subnets.py +433 -0
- runbooks/inventory/list_vpcs.py +422 -0
- runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
- runbooks/inventory/models/__init__.py +24 -0
- runbooks/inventory/models/account.py +192 -0
- runbooks/inventory/models/inventory.py +309 -0
- runbooks/inventory/models/resource.py +247 -0
- runbooks/inventory/recover_cfn_stack_ids.py +205 -0
- runbooks/inventory/requirements.txt +12 -0
- runbooks/inventory/run_on_multi_accounts.py +211 -0
- runbooks/inventory/tests/common_test_data.py +3661 -0
- runbooks/inventory/tests/common_test_functions.py +204 -0
- runbooks/inventory/tests/script_test_data.py +0 -0
- runbooks/inventory/tests/setup.py +24 -0
- runbooks/inventory/tests/src.py +18 -0
- runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
- runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
- runbooks/inventory/tests/test_inventory_modules.py +55 -0
- runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
- runbooks/inventory/tests/test_moto_integration_example.py +273 -0
- runbooks/inventory/tests/test_org_list_accounts.py +49 -0
- runbooks/inventory/update_aws_actions.py +173 -0
- runbooks/inventory/update_cfn_stacksets.py +1215 -0
- runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
- runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
- runbooks/inventory/update_s3_public_access_block.py +539 -0
- runbooks/inventory/utils/__init__.py +23 -0
- runbooks/inventory/utils/aws_helpers.py +510 -0
- runbooks/inventory/utils/threading_utils.py +493 -0
- runbooks/inventory/utils/validation.py +682 -0
- runbooks/inventory/verify_ec2_security_groups.py +1430 -0
- runbooks/main.py +785 -0
- runbooks/organizations/__init__.py +12 -0
- runbooks/organizations/manager.py +374 -0
- runbooks/security_baseline/README.md +324 -0
- runbooks/security_baseline/checklist/alternate_contacts.py +8 -1
- runbooks/security_baseline/checklist/bucket_public_access.py +4 -1
- runbooks/security_baseline/checklist/cloudwatch_alarm_configuration.py +9 -2
- runbooks/security_baseline/checklist/guardduty_enabled.py +9 -2
- runbooks/security_baseline/checklist/multi_region_instance_usage.py +5 -1
- runbooks/security_baseline/checklist/root_access_key.py +6 -1
- runbooks/security_baseline/config-origin.json +1 -1
- runbooks/security_baseline/config.json +1 -1
- runbooks/security_baseline/permission.json +1 -1
- runbooks/security_baseline/report_generator.py +10 -2
- runbooks/security_baseline/report_template_en.html +8 -8
- runbooks/security_baseline/report_template_jp.html +8 -8
- runbooks/security_baseline/report_template_kr.html +13 -13
- runbooks/security_baseline/report_template_vn.html +8 -8
- runbooks/security_baseline/requirements.txt +7 -0
- runbooks/security_baseline/run_script.py +8 -2
- runbooks/security_baseline/security_baseline_tester.py +10 -2
- runbooks/security_baseline/utils/common.py +5 -1
- runbooks/utils/__init__.py +204 -0
- runbooks-0.6.1.dist-info/METADATA +373 -0
- runbooks-0.6.1.dist-info/RECORD +237 -0
- {runbooks-0.2.3.dist-info → runbooks-0.6.1.dist-info}/WHEEL +1 -1
- runbooks-0.6.1.dist-info/entry_points.txt +7 -0
- runbooks-0.6.1.dist-info/licenses/LICENSE +201 -0
- runbooks-0.6.1.dist-info/top_level.txt +3 -0
- runbooks/python101/calculator.py +0 -34
- runbooks/python101/config.py +0 -1
- runbooks/python101/exceptions.py +0 -16
- runbooks/python101/file_manager.py +0 -218
- runbooks/python101/toolkit.py +0 -153
- runbooks-0.2.3.dist-info/METADATA +0 -435
- runbooks-0.2.3.dist-info/RECORD +0 -61
- runbooks-0.2.3.dist-info/entry_points.txt +0 -3
- runbooks-0.2.3.dist-info/top_level.txt +0 -1
@@ -0,0 +1,204 @@
|
|
1
|
+
import pytest
|
2
|
+
from botocore import client, session
|
3
|
+
|
4
|
+
ERASE_LINE = "\x1b[2K"
|
5
|
+
|
6
|
+
|
7
|
+
def AWSAccount_from_AWSKeyID(AWSKeyID):
|
8
|
+
"""
|
9
|
+
Determines the AWS Account number from the AWS Key ID.
|
10
|
+
The original idea here: https://hackingthe.cloud/aws/enumeration/get-account-id-from-keys/
|
11
|
+
@param AWSKeyID: This is a *fake* AWS Key in the format of "xxxx" (four characters)
|
12
|
+
and then should be the account number. We'll toss out the rest of the data as irrelevant
|
13
|
+
@return: Returns the account number as a string
|
14
|
+
"""
|
15
|
+
trimmed_AWSKeyID = AWSKeyID[4:16] # remove KeyID prefix
|
16
|
+
return str(trimmed_AWSKeyID)
|
17
|
+
|
18
|
+
|
19
|
+
def AWSKeyID_from_AWSAccount(AWSAccountNumber):
|
20
|
+
"""
|
21
|
+
Makes up an AWS Key ID from the AWS Account number.
|
22
|
+
@param AWSAccountNumber: This is the AWS Account number as a string
|
23
|
+
@return: Returns the AWS Key ID as a string
|
24
|
+
"""
|
25
|
+
# An AWS Key looks like this: "AIDAJ74HIVAJJXOVUHYO6" (21 characters)
|
26
|
+
AWSKey = f"xxxx{str(AWSAccountNumber)}xxxxx"
|
27
|
+
return AWSKey
|
28
|
+
|
29
|
+
|
30
|
+
def _amend_create_boto3_session(test_data, mocker):
|
31
|
+
orig = session.Session.create_client
|
32
|
+
|
33
|
+
def amend_create_client(
|
34
|
+
self,
|
35
|
+
service_name,
|
36
|
+
region_name=None,
|
37
|
+
api_version=None,
|
38
|
+
use_ssl=True,
|
39
|
+
verify=None,
|
40
|
+
endpoint_url=None,
|
41
|
+
aws_access_key_id=None,
|
42
|
+
aws_secret_access_key=None,
|
43
|
+
aws_session_token=None,
|
44
|
+
config=None,
|
45
|
+
):
|
46
|
+
# Intercept boto3 Session, in hopes of sending back a client that includes the Account Number
|
47
|
+
# if aws_access_key_id == '*****AccessKeyHere*****':
|
48
|
+
print(test_data["FunctionName"])
|
49
|
+
if aws_access_key_id == "MeantToFail":
|
50
|
+
print(f"Failed Access Key: {aws_access_key_id}")
|
51
|
+
return ()
|
52
|
+
else:
|
53
|
+
print(f"Not Failed Access Key: {aws_access_key_id}")
|
54
|
+
return_response = orig(
|
55
|
+
self,
|
56
|
+
service_name,
|
57
|
+
region_name,
|
58
|
+
api_version,
|
59
|
+
use_ssl,
|
60
|
+
verify,
|
61
|
+
endpoint_url,
|
62
|
+
aws_access_key_id,
|
63
|
+
aws_secret_access_key,
|
64
|
+
aws_session_token,
|
65
|
+
config,
|
66
|
+
)
|
67
|
+
return return_response
|
68
|
+
|
69
|
+
mocker.patch("botocore.session.Session.create_client", new=amend_create_client)
|
70
|
+
print()
|
71
|
+
|
72
|
+
|
73
|
+
def _amend_make_api_call_orig(test_key, test_value, mocker):
|
74
|
+
orig = client.BaseClient._make_api_call
|
75
|
+
|
76
|
+
def amend_make_api_call(self, operation_name, kwargs):
|
77
|
+
# Intercept boto3 operations for <secretsmanager.get_secret_value>. Optionally, you can also
|
78
|
+
# check on the argument <SecretId> and control how you want the response would be. This is
|
79
|
+
# a very flexible solution as you have full control over the whole process of fetching a
|
80
|
+
# secret.
|
81
|
+
if operation_name == "ListAccounts":
|
82
|
+
if isinstance(test_value, Exception):
|
83
|
+
raise test_value
|
84
|
+
# Implied break and exit of the function here...
|
85
|
+
print(
|
86
|
+
f"Operation Name mocked: {operation_name}\n"
|
87
|
+
f"Key Name: {test_key}\n"
|
88
|
+
f"kwargs: {kwargs}\n"
|
89
|
+
f"mocked return_response: {test_value}"
|
90
|
+
)
|
91
|
+
return test_value
|
92
|
+
|
93
|
+
return_response = orig(self, operation_name, kwargs)
|
94
|
+
print(
|
95
|
+
f"Operation Name passed through: {operation_name}\n"
|
96
|
+
f"Key name: {test_key}\n"
|
97
|
+
f"kwargs: {kwargs}\n"
|
98
|
+
f"Actual return response: {return_response}"
|
99
|
+
)
|
100
|
+
return return_response
|
101
|
+
|
102
|
+
mocker.patch("botocore.client.BaseClient._make_api_call", new=amend_make_api_call)
|
103
|
+
|
104
|
+
|
105
|
+
def _amend_make_api_call(meta_key_dict, test_dict, mocker):
|
106
|
+
orig = client.BaseClient._make_api_call
|
107
|
+
|
108
|
+
def amend_make_api_call(self, operation_name, kwargs):
|
109
|
+
# Intercept boto3 operations for <secretsmanager.get_secret_value>. Optionally, you can also
|
110
|
+
# check on the argument <SecretId> and control how you want the response would be. This is
|
111
|
+
# a very flexible solution as you have full control over the whole process of fetching a
|
112
|
+
# secret.
|
113
|
+
for op_name in test_dict:
|
114
|
+
test_value = op_name["test_result"]
|
115
|
+
region = self.meta.region_name
|
116
|
+
if operation_name == op_name["operation_name"]:
|
117
|
+
if isinstance(test_value, Exception):
|
118
|
+
# Implied break and exit of the function here...
|
119
|
+
raise test_value
|
120
|
+
print(
|
121
|
+
f"Operation Name mocked: {operation_name}\n"
|
122
|
+
f"Function Name: {meta_key_dict['FunctionName']}\n"
|
123
|
+
f"kwargs: {kwargs}\n"
|
124
|
+
f"mocked return_response: {op_name['test_result']}"
|
125
|
+
)
|
126
|
+
return op_name["test_result"]
|
127
|
+
try:
|
128
|
+
print(
|
129
|
+
f"Trying: Operation Name passed through: {operation_name}\n"
|
130
|
+
f"Key Name: {meta_key_dict['FunctionName']}\n"
|
131
|
+
f"kwargs: {kwargs}\n"
|
132
|
+
)
|
133
|
+
return_response = orig(self, operation_name, kwargs)
|
134
|
+
print(f"Actual return_response: {return_response}")
|
135
|
+
except Exception as my_Error:
|
136
|
+
raise ConnectionError("Operation Failed")
|
137
|
+
return return_response
|
138
|
+
|
139
|
+
mocker.patch("botocore.client.BaseClient._make_api_call", new=amend_make_api_call)
|
140
|
+
|
141
|
+
|
142
|
+
def _amend_make_api_call_specific(meta_key_dict, test_dict, mocker):
|
143
|
+
orig = client.BaseClient._make_api_call
|
144
|
+
|
145
|
+
def amend_make_api_call(self, operation_name, kwargs):
|
146
|
+
# Intercept boto3 operations for <secretsmanager.get_secret_value>. Optionally, you can also
|
147
|
+
# check on the argument <SecretId> and control how you want the response would be. This is
|
148
|
+
# a very flexible solution as you have full control over the whole process of fetching a
|
149
|
+
# secret.
|
150
|
+
# This goes through the operations in the dictionary and checks for each operation, whether it matches the operation we're patching right now.
|
151
|
+
for op_name in test_dict:
|
152
|
+
if operation_name == op_name["operation_name"]:
|
153
|
+
# We are able to capture the region from the API call, and use that to differentiate data to return
|
154
|
+
region = self.meta.region_name
|
155
|
+
# For the various sets of return data that we have...
|
156
|
+
test_value = None
|
157
|
+
for set_of_result_data in op_name["test_result"]:
|
158
|
+
# Check to see which set of return data matches the region we're calling for now...
|
159
|
+
if set_of_result_data["Region"] == region:
|
160
|
+
test_value = set_of_result_data["mocked_response"]
|
161
|
+
break
|
162
|
+
if test_value is not None and isinstance(test_value, Exception):
|
163
|
+
# Implied break and exit of the function here...
|
164
|
+
print("Expected Error...")
|
165
|
+
raise test_value
|
166
|
+
elif test_value is None:
|
167
|
+
print(f"No test data offered for this credentials in region {region}")
|
168
|
+
continue
|
169
|
+
print(
|
170
|
+
f"Operation Name mocked: {operation_name}\n"
|
171
|
+
f"Function Name: {meta_key_dict['FunctionName']}\n"
|
172
|
+
f"kwargs: {kwargs}\n"
|
173
|
+
f"mocked return_response: {test_value}"
|
174
|
+
)
|
175
|
+
return test_value
|
176
|
+
|
177
|
+
print(
|
178
|
+
f"Operation Name passed through: {operation_name}\n"
|
179
|
+
f"Function Name: {meta_key_dict['FunctionName']}\n"
|
180
|
+
f"kwargs: {kwargs}\n"
|
181
|
+
)
|
182
|
+
return_response = orig(self, operation_name, kwargs)
|
183
|
+
print(f"Actual return_response: {return_response}")
|
184
|
+
return return_response
|
185
|
+
|
186
|
+
mocker.patch("botocore.client.BaseClient._make_api_call", new=amend_make_api_call)
|
187
|
+
|
188
|
+
|
189
|
+
# mocker.patch('botocore.session', new=amend_make_api_call)
|
190
|
+
|
191
|
+
|
192
|
+
def mock_find_all_instances2(creds: dict, region: str):
|
193
|
+
"""
|
194
|
+
This is a mock function that will return a list of all the instances in the region that we're looking for.
|
195
|
+
:param creds: Credentials object, where 'AccountNumber' is the account number of the account that we're looking for.
|
196
|
+
:param region: string for region we're checking
|
197
|
+
:return: The output from the EC2 API for "list_instances"
|
198
|
+
"""
|
199
|
+
from Tests.common_test_data import All_Instances_Response_Data
|
200
|
+
|
201
|
+
for mock_data_set in All_Instances_Response_Data:
|
202
|
+
if mock_data_set["Region"] == region and mock_data_set["AccountNumber"] == creds["AccountNumber"]:
|
203
|
+
return mock_data_set["instance_data"]
|
204
|
+
raise KeyError(f"No data for {creds['AccountNumber']} found for region {region}")
|
File without changes
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from setuptools import setup
|
2
|
+
|
3
|
+
setup(
|
4
|
+
name="cli_skeleton", # Update Name
|
5
|
+
packages=["cli_skeleton"], # Name of CLI
|
6
|
+
version="0.1.0", # Version
|
7
|
+
description="A cli for X", # Description
|
8
|
+
author="NAME", # Author
|
9
|
+
url="https://github.com/REPO", # To be updated
|
10
|
+
author_email="NAME@EMAIL.com", # Email
|
11
|
+
download_url="https://github.com/REPO", # To be updated
|
12
|
+
keywords=["aws", "python"], # Key words for cli
|
13
|
+
classifiers=[],
|
14
|
+
install_requires=[
|
15
|
+
"PACKAGE" # Add all packages
|
16
|
+
],
|
17
|
+
setup_requires=[],
|
18
|
+
tests_require=[],
|
19
|
+
entry_points={
|
20
|
+
"console_scripts": [
|
21
|
+
"cli_skeleton = cli_skeleton.__main__:main",
|
22
|
+
],
|
23
|
+
},
|
24
|
+
)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import boto3
|
2
|
+
from account_class import aws_acct_access
|
3
|
+
|
4
|
+
sendgrid_api_key_arn = "some_name"
|
5
|
+
region_name = "us-east-1"
|
6
|
+
credentials = {"profile_name": "LZ1"}
|
7
|
+
|
8
|
+
|
9
|
+
def do_stuff():
|
10
|
+
# aws_acct = aws_acct_access()
|
11
|
+
# session = boto3.session.Session(**credentials)
|
12
|
+
# client = session.client(service_name="organizations", region_name=region_name)
|
13
|
+
# response1 = client.list_accounts()
|
14
|
+
# response2 = client.list_roots()
|
15
|
+
# responsedict = {'response1': response1, 'response2': response2, 'response3': aws_acct}
|
16
|
+
# # responsedict = {'response1': response1, 'response2': response2}
|
17
|
+
# return responsedict
|
18
|
+
print("Hello World")
|
@@ -0,0 +1,208 @@
|
|
1
|
+
import sys
|
2
|
+
import unittest
|
3
|
+
from io import StringIO
|
4
|
+
from pprint import pprint
|
5
|
+
from unittest.mock import MagicMock, patch
|
6
|
+
|
7
|
+
import pytest
|
8
|
+
|
9
|
+
# Import the functions you want to test
|
10
|
+
from cfn_describe_stacks import (
|
11
|
+
collect_cfnstacks,
|
12
|
+
display_stacks,
|
13
|
+
modify_stacks,
|
14
|
+
parse_args,
|
15
|
+
setup_auth_accounts_and_regions,
|
16
|
+
)
|
17
|
+
|
18
|
+
|
19
|
+
class TestScriptFunctions(unittest.TestCase):
|
20
|
+
def setUp(self):
|
21
|
+
# This is the parameters provided.
|
22
|
+
self.mock_profile = "mock_profile"
|
23
|
+
self.mock_regions = ["us-east-1", "us-west-1"]
|
24
|
+
self.fragments = ["Stack"]
|
25
|
+
self.accounts = ["123456789012", "234567890123"]
|
26
|
+
self.exact = False
|
27
|
+
self.timing = True
|
28
|
+
self.SkipAccounts = None
|
29
|
+
self.SkipProfiles = None
|
30
|
+
self.loglevel = 50
|
31
|
+
self.status = None
|
32
|
+
self.stackid = False
|
33
|
+
self.rootonly = False
|
34
|
+
self.deletionrun = False
|
35
|
+
# This is the parameters that will be passed to the script
|
36
|
+
self.mock_args = ["-p", self.mock_profile, "-rs", self.mock_regions, "--time", "-f", self.fragments]
|
37
|
+
# This is the parameters that have been instantiated within the script, including default values
|
38
|
+
self.expected_args = {
|
39
|
+
# 'AccessRoles' : None,
|
40
|
+
"Accounts": self.accounts,
|
41
|
+
"DeletionRun": self.deletionrun,
|
42
|
+
"Exact": self.exact,
|
43
|
+
"Fragments": self.fragments,
|
44
|
+
"Profile": self.mock_profile,
|
45
|
+
"Regions": self.mock_regions,
|
46
|
+
"RootOnly": self.rootonly,
|
47
|
+
"SkipAccounts": self.SkipAccounts,
|
48
|
+
"SkipProfiles": self.SkipProfiles,
|
49
|
+
"Time": self.timing,
|
50
|
+
"loglevel": self.loglevel,
|
51
|
+
"stackid": self.stackid,
|
52
|
+
"status": self.status,
|
53
|
+
# Add other expected arguments as needed
|
54
|
+
}
|
55
|
+
|
56
|
+
def test_parse_args(self):
|
57
|
+
with patch("sys.argv", self.mock_args):
|
58
|
+
args = parse_args(sys.argv)
|
59
|
+
for arg, value in self.expected_args.items():
|
60
|
+
self.assertEqual(getattr(args, arg), value)
|
61
|
+
|
62
|
+
@patch("all_my_cfnstacks.aws_acct_access")
|
63
|
+
@patch("all_my_cfnstacks.Inventory_Modules.get_regions3")
|
64
|
+
# @patch('all_my_cfnstacks.Inventory_Modules.RemoveCoreAccounts')
|
65
|
+
# def test_setup_auth_accounts_and_regions(self, mock_remove_core_accounts, mock_get_regions3, mock_aws_acct_access):
|
66
|
+
def test_setup_auth_accounts_and_regions(self, mock_get_regions3, mock_aws_acct):
|
67
|
+
# Set up mock objects and data
|
68
|
+
mock_aws_acct_access = MagicMock()
|
69
|
+
mock_aws_acct_access.ChildAccounts = [{"AccountId": "123456789012"}, {"AccountId": "234567890123"}]
|
70
|
+
mock_aws_acct.return_value = mock_aws_acct_access
|
71
|
+
# mock_aws_acct.ChildAccounts = [{'AccountId': '123456789012'}, {'AccountId': '234567890123'}]
|
72
|
+
mock_get_regions3.return_value = ["us-east-1", "us-west-1"]
|
73
|
+
# mock_remove_core_accounts.return_value =
|
74
|
+
# mock_remove_core_accounts.side_effect = lambda accounts, skip_accounts: accounts
|
75
|
+
|
76
|
+
# Call the function
|
77
|
+
aws_acct, account_list, region_list = setup_auth_accounts_and_regions(
|
78
|
+
self.mock_profile,
|
79
|
+
mock_get_regions3,
|
80
|
+
self.accounts,
|
81
|
+
self.SkipAccounts,
|
82
|
+
self.fragments,
|
83
|
+
self.exact,
|
84
|
+
self.deletionrun,
|
85
|
+
)
|
86
|
+
|
87
|
+
# Assert the results
|
88
|
+
self.assertEqual(aws_acct, mock_aws_acct.return_value)
|
89
|
+
self.assertEqual(account_list, ["123456789012", "234567890123"])
|
90
|
+
self.assertEqual(region_list, mock_get_regions3.return_value)
|
91
|
+
|
92
|
+
@patch("all_my_cfnstacks.Inventory_Modules.find_stacks2")
|
93
|
+
def test_collect_cfnstacks(self, mock_find_stacks2):
|
94
|
+
# Set up mock data
|
95
|
+
mock_credential_list = [
|
96
|
+
{"AccountId": "123456789012", "Region": "us-east-1", "Success": True},
|
97
|
+
{"AccountId": "234567890123", "Region": "us-west-1", "Success": False},
|
98
|
+
]
|
99
|
+
mock_stacks = [
|
100
|
+
{
|
101
|
+
"StackName": "my-stack-1",
|
102
|
+
"StackStatus": "CREATE_COMPLETE",
|
103
|
+
"StackId": "arn:aws:cloudformation:...",
|
104
|
+
"CreationTime": "2023-04-01T00:00:00Z",
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"StackName": "my-stack-2",
|
108
|
+
"StackStatus": "UPDATE_IN_PROGRESS",
|
109
|
+
"StackId": "arn:aws:cloudformation:...",
|
110
|
+
"CreationTime": "2023-04-02T00:00:00Z",
|
111
|
+
},
|
112
|
+
]
|
113
|
+
mock_find_stacks2.return_value = mock_stacks
|
114
|
+
|
115
|
+
# Call the function
|
116
|
+
all_stacks = collect_cfnstacks(mock_credential_list)
|
117
|
+
|
118
|
+
# Assert the results
|
119
|
+
expected_stacks = [
|
120
|
+
{
|
121
|
+
"Account": "123456789012",
|
122
|
+
"Region": "us-east-1",
|
123
|
+
"AccessKeyId": None,
|
124
|
+
"SecretAccessKey": None,
|
125
|
+
"SessionToken": None,
|
126
|
+
"AccountNumber": None,
|
127
|
+
"StackName": "my-stack-1",
|
128
|
+
"StackCreate": None,
|
129
|
+
}
|
130
|
+
]
|
131
|
+
|
132
|
+
# Need some asserts here
|
133
|
+
|
134
|
+
@patch("script.display_results")
|
135
|
+
@patch("builtins.print")
|
136
|
+
def test_display_stacks(self, mock_print, mock_display_results):
|
137
|
+
global AccountList, RegionList
|
138
|
+
AccountList = ["111111111111", "222222222222"]
|
139
|
+
RegionList = ["us-east-1", "us-west-2"]
|
140
|
+
all_stacks = [
|
141
|
+
{
|
142
|
+
"Account": "111111111111",
|
143
|
+
"Region": "us-east-1",
|
144
|
+
"StackStatus": "CREATE_COMPLETE",
|
145
|
+
"StackCreate": "2023-04-01",
|
146
|
+
"StackName": "stack1",
|
147
|
+
"StackArn": "arn:aws:cloudformation:us-east-1:111111111111:stack/stack1/abcd1234",
|
148
|
+
},
|
149
|
+
{
|
150
|
+
"Account": "222222222222",
|
151
|
+
"Region": "us-west-2",
|
152
|
+
"StackStatus": "UPDATE_COMPLETE",
|
153
|
+
"StackCreate": "2023-03-15",
|
154
|
+
"StackName": "stack2",
|
155
|
+
"StackArn": "arn:aws:cloudformation:us-west-2:222222222222:stack/stack2/efgh5678",
|
156
|
+
},
|
157
|
+
]
|
158
|
+
|
159
|
+
display_stacks(all_stacks)
|
160
|
+
|
161
|
+
mock_display_results.assert_called_once()
|
162
|
+
expected_print_calls = [
|
163
|
+
mock.call("\x1b[2K"),
|
164
|
+
mock.call("\x1b[31mFound 2 stacks across 2 accounts across 2 regions\x1b[0m"),
|
165
|
+
mock.call(),
|
166
|
+
mock.call("The list of accounts and regions:"),
|
167
|
+
mock.ANY, # Skipping the pprint call
|
168
|
+
]
|
169
|
+
mock_print.assert_has_calls(expected_print_calls)
|
170
|
+
|
171
|
+
@patch("builtins.input", return_value="y")
|
172
|
+
@patch("all_my_cfnstacks.Inventory_Modules.delete_stack2")
|
173
|
+
def test_modify_stacks(self, mock_delete_stack2, mock_input):
|
174
|
+
global pStackfrag, DeletionRun
|
175
|
+
pStackfrag = "my-stack"
|
176
|
+
DeletionRun = True
|
177
|
+
|
178
|
+
stack_found1 = {
|
179
|
+
"Account": "111111111111",
|
180
|
+
"Region": "us-east-1",
|
181
|
+
"StackName": "stack1",
|
182
|
+
"StackStatus": "CREATE_COMPLETE",
|
183
|
+
}
|
184
|
+
stack_found2 = {
|
185
|
+
"Account": "222222222222",
|
186
|
+
"Region": "us-west-2",
|
187
|
+
"StackName": "stack2",
|
188
|
+
"StackStatus": "DELETE_FAILED",
|
189
|
+
}
|
190
|
+
stacks_found = [stack_found1, stack_found2]
|
191
|
+
|
192
|
+
mock_delete_stack2.side_effect = ["delete_response1", "delete_response2"]
|
193
|
+
|
194
|
+
modify_result = modify_stacks(stacks_found)
|
195
|
+
|
196
|
+
self.assertEqual(modify_result, ["delete_response1", "delete_response2"])
|
197
|
+
mock_input.assert_called_once_with("Deletion of stacks has been requested, are you still sure? (y/n): ")
|
198
|
+
mock_delete_stack2.assert_any_call(stack_found1, "us-east-1", "stack1")
|
199
|
+
mock_delete_stack2.assert_any_call(
|
200
|
+
stack_found2,
|
201
|
+
"us-west-2",
|
202
|
+
"stack2",
|
203
|
+
RetainResources=True,
|
204
|
+
)
|
205
|
+
|
206
|
+
|
207
|
+
if __name__ == "__main__":
|
208
|
+
unittest.main()
|
@@ -0,0 +1,162 @@
|
|
1
|
+
"""
|
2
|
+
python
|
3
|
+
"""
|
4
|
+
|
5
|
+
import sys
|
6
|
+
import unittest
|
7
|
+
from unittest.mock import patch
|
8
|
+
|
9
|
+
import pytest
|
10
|
+
from common_test_data import (
|
11
|
+
All_Instances_Response_Data,
|
12
|
+
CredentialResponseData,
|
13
|
+
mock_instances_1,
|
14
|
+
mock_profile_list_1,
|
15
|
+
mock_profile_list_2,
|
16
|
+
mock_profile_list_3,
|
17
|
+
mock_profile_list_4,
|
18
|
+
mock_region_list_1,
|
19
|
+
mock_region_list_2,
|
20
|
+
mock_region_list_3,
|
21
|
+
mock_region_list_4,
|
22
|
+
)
|
23
|
+
from common_test_functions import mock_find_all_instances2
|
24
|
+
from ec2_describe_instances import find_all_instances, parse_args
|
25
|
+
|
26
|
+
|
27
|
+
class TestScriptFunctions(unittest.TestCase):
|
28
|
+
def setUp(self):
|
29
|
+
# This is the parameters provided. Note that this
|
30
|
+
self.account_mapping = [
|
31
|
+
{"AccountNumber": "111122223333", "Region": "us-east-1", "mock_instances_returned": "mock_instances_1"},
|
32
|
+
{"AccountNumber": "444455556666", "Region": "us-east-2", "mock_instances_returned": "mock_instances_2"},
|
33
|
+
{"AccountNumber": "555566667777", "Region": "us-west-2", "mock_instances_returned": "mock_instances_3"},
|
34
|
+
{"AccountNumber": "555566667777", "Region": "eu-west-1", "mock_instances_returned": "mock_instances_4"},
|
35
|
+
{"AccountNumber": "666677775555", "Region": "eu-central-1", "mock_instances_returned": "mock_instances_5"},
|
36
|
+
{"AccountNumber": "777755556666", "Region": "eu-north-1", "mock_instances_returned": "mock_instances_6"},
|
37
|
+
{"AccountNumber": "777755556666", "Region": "eu-west-2", "mock_instances_returned": "mock_instances_7"},
|
38
|
+
{"AccountNumber": "666677778888", "Region": "ap-south-1", "mock_instances_returned": "mock_instances_8"},
|
39
|
+
{"AccountNumber": "777788886666", "Region": "il-central-1", "mock_instances_returned": "mock_instances_9"},
|
40
|
+
{"AccountNumber": "888866667777", "Region": "af-south-1", "mock_instances_returned": "mock_instances_10"},
|
41
|
+
]
|
42
|
+
self.expected_args = {
|
43
|
+
"AccessRoles": None,
|
44
|
+
"Accounts": None,
|
45
|
+
"Profiles": ["mock_profile"],
|
46
|
+
"Regions": ["us-east-1"],
|
47
|
+
"RootOnly": False,
|
48
|
+
"SkipAccounts": None,
|
49
|
+
"SkipProfiles": None,
|
50
|
+
"Time": True,
|
51
|
+
"loglevel": 20,
|
52
|
+
"pStatus": "running",
|
53
|
+
# Add other expected arguments as needed
|
54
|
+
}
|
55
|
+
self.mock_args = ["-p", "mock_profile", "-rs", "us-east-1", "-s", "running", "--time", "-vvv"]
|
56
|
+
self.mock_profile_list = ["mock_profile_1", "mock_profile_2"]
|
57
|
+
self.mock_region_list = ["us-east-1", "us-east-2"]
|
58
|
+
|
59
|
+
# This is the parameters that have been instantiated within the script, including default values
|
60
|
+
|
61
|
+
def test_parse_args(self):
|
62
|
+
with patch("sys.argv", self.mock_args):
|
63
|
+
args = parse_args(sys.argv)
|
64
|
+
for arg, value in self.expected_args.items():
|
65
|
+
self.assertEqual(getattr(args, arg), value)
|
66
|
+
|
67
|
+
# @patch('all_my_instances.Inventory_Modules.get_regions3')
|
68
|
+
# @patch('all_my_instances.Inventory_Modules.get_profiles')
|
69
|
+
# @patch('all_my_instances.get_credentials_for_accounts_in_org')
|
70
|
+
|
71
|
+
# # @pytest.mark.parametrize(
|
72
|
+
# "mock_org_credentials, mock_profile_list, mock_region_list",
|
73
|
+
# [
|
74
|
+
# (CredentialResponseData, mock_profile_list_1, mock_region_list_1),
|
75
|
+
# (CredentialResponseData, mock_profile_list_2, mock_region_list_2),
|
76
|
+
# (CredentialResponseData, mock_profile_list_3, mock_region_list_3),
|
77
|
+
# (CredentialResponseData, mock_profile_list_4, mock_region_list_4),
|
78
|
+
# ],
|
79
|
+
# )
|
80
|
+
# def test_get_credentials(self, mock_get_credentials_for_accounts_in_org, mock_get_profiles, mock_get_regions3, mock_org_credentials, mock_profile_list, mock_region_list):
|
81
|
+
|
82
|
+
"""
|
83
|
+
def test_get_credentials(self, mock_get_credentials_for_accounts_in_org, mock_get_profiles, mock_get_regions3):
|
84
|
+
mock_get_profiles.return_value = self.mock_profile_list
|
85
|
+
mock_get_regions3.return_value = self.mock_region_list
|
86
|
+
mock_get_credentials_for_accounts_in_org.return_value = CredentialResponseData
|
87
|
+
|
88
|
+
# The credentials supplied here absolutely do not matter, since the Credential Response is also hard-coded above.
|
89
|
+
# def get_credentials(fProfile_list: list, fRegion_list: list, fSkipProfiles: list = None, fSkipAccounts: list = None, fRootOnly: bool = False, fAccounts: list = None, fAccessRoles: list = None, fTiming=False) -> list:
|
90
|
+
credentials = get_credentials(mock_get_profiles, mock_get_regions3)
|
91
|
+
self.assertEqual(len(credentials), len(self.mock_profile_list) * len(CredentialResponseData))
|
92
|
+
self.assertEqual(credentials[0]['MgmtAccount'], '111122223333')
|
93
|
+
self.assertEqual(credentials[0]['AccountId'], '111122223333')
|
94
|
+
self.assertEqual(credentials[0]['Region'], 'us-east-1')
|
95
|
+
self.assertEqual(credentials[0]['Profile'], 'mock_profile')
|
96
|
+
self.assertEqual(credentials[0]['AccountStatus'], 'ACTIVE')
|
97
|
+
self.assertEqual(credentials[0]['Role'], 'Use Profile')
|
98
|
+
self.assertEqual(credentials[1]['MgmtAccount'], '111122223333')
|
99
|
+
self.assertEqual(credentials[1]['AccountId'], '444455556666')
|
100
|
+
self.assertEqual(credentials[1]['Region'], 'us-east-2')
|
101
|
+
self.assertEqual(credentials[1]['Profile'], None)
|
102
|
+
self.assertEqual(credentials[1]['AccountStatus'], 'ACTIVE')
|
103
|
+
self.assertEqual(credentials[1]['Role'], 'AWSCloudFormationStackSetExecutionRole')
|
104
|
+
"""
|
105
|
+
|
106
|
+
@patch("all_my_instances.Inventory_Modules.find_account_instances2", wraps=mock_find_all_instances2)
|
107
|
+
def test_find_all_instances(self, mock_find_account_instances2):
|
108
|
+
test_creds = CredentialResponseData[1:3]
|
109
|
+
instances = find_all_instances(test_creds, "running")
|
110
|
+
# self.assertEqual(len(instances), (len(mock_instances_1) * len(CredentialResponseData)))
|
111
|
+
for mock_profile in All_Instances_Response_Data:
|
112
|
+
for instance in instances:
|
113
|
+
mock_data_set = (
|
114
|
+
mock_profile["instance_data"]["Reservations"]
|
115
|
+
if mock_profile["mock_profile"] == instance["ParentProfile"]
|
116
|
+
else None
|
117
|
+
)
|
118
|
+
|
119
|
+
self.assertEqual(instances[0]["InstanceType"], "t2.micro")
|
120
|
+
self.assertEqual(instances[0]["InstanceId"], "i-1234567890abcdef")
|
121
|
+
self.assertEqual(instances[0]["PublicDNSName"], "ec2-1-2-3-4.us-east-1.compute.amazonaws.com")
|
122
|
+
self.assertEqual(instances[0]["State"], "running")
|
123
|
+
self.assertEqual(instances[0]["Name"], "Instance1")
|
124
|
+
self.assertEqual(instances[0]["AccountId"], "111122223333")
|
125
|
+
self.assertEqual(instances[0]["Region"], "us-east-1")
|
126
|
+
self.assertEqual(instances[0]["MgmtAccount"], "111122223333")
|
127
|
+
self.assertEqual(instances[0]["ParentProfile"], "mock_profile")
|
128
|
+
|
129
|
+
# def test_main(self):
|
130
|
+
# # Capture the output of the script
|
131
|
+
# captured_output = StringIO()
|
132
|
+
# sys.stdout = captured_output
|
133
|
+
#
|
134
|
+
# # Call the main function with mock arguments
|
135
|
+
# with patch('sys.argv', self.mock_args):
|
136
|
+
# with patch('all_my_instances.get_credentials', return_value=CredentialResponseData):
|
137
|
+
# with patch('all_my_instances.find_all_instances',
|
138
|
+
# return_value=[{'InstanceType': 't2.micro',
|
139
|
+
# 'InstanceId' : 'i-1234567890abcdef',
|
140
|
+
# 'State' : 'running'}]):
|
141
|
+
# all_my_instances.init()
|
142
|
+
#
|
143
|
+
# # Restore the original stdout
|
144
|
+
# sys.stdout = sys.__stdout__
|
145
|
+
#
|
146
|
+
# # Check the captured output
|
147
|
+
# output = captured_output.getvalue()
|
148
|
+
# self.assertIn('Found 1 instances across 1 accounts across 1 regions', output)
|
149
|
+
|
150
|
+
|
151
|
+
if __name__ == "__main__":
|
152
|
+
unittest.main()
|
153
|
+
|
154
|
+
"""
|
155
|
+
In the test_find_all_instances method, I added assertions to check if the instance details are correctly populated in the returned list.
|
156
|
+
|
157
|
+
Additionally, I added a test_main method to test the main function of the script. This test captures the output of the script using StringIO and checks if the expected output is present in the captured output.
|
158
|
+
|
159
|
+
Note that I've used the patch decorator from the unittest.mock module to mock the get_credentials and find_all_instances functions in the test_main method. You might need to adjust the mocked return values based on your specific use case.
|
160
|
+
|
161
|
+
With these additions, the unit test script should be complete and ready to run using python test_script.py (assuming the test script file is named test_script.py).
|
162
|
+
"""
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import pytest
|
2
|
+
from common_test_data import (
|
3
|
+
AssumeRoleResponseData,
|
4
|
+
DescribeOrganizationsResponseData,
|
5
|
+
DescribeRegionsResponseData,
|
6
|
+
GetCallerIdentity,
|
7
|
+
ListAccountsResponseData,
|
8
|
+
cli_provided_parameters1,
|
9
|
+
)
|
10
|
+
from common_test_functions import _amend_make_api_call
|
11
|
+
from Inventory_Modules import get_all_credentials
|
12
|
+
|
13
|
+
get_all_credentials_test_result_dict = [
|
14
|
+
{"operation_name": "GetCallerIdentity", "test_result": GetCallerIdentity},
|
15
|
+
{"operation_name": "DescribeOrganization", "test_result": DescribeOrganizationsResponseData},
|
16
|
+
{"operation_name": "AssumeRole", "test_result": AssumeRoleResponseData},
|
17
|
+
{"operation_name": "ListAccounts", "test_result": ListAccountsResponseData},
|
18
|
+
{"operation_name": "DescribeRegions", "test_result": DescribeRegionsResponseData},
|
19
|
+
]
|
20
|
+
|
21
|
+
|
22
|
+
# Skipped for now, since I know the get_credential testing needs more work
|
23
|
+
@pytest.mark.skip
|
24
|
+
@pytest.mark.parametrize(
|
25
|
+
"parameters, test_value_dict",
|
26
|
+
[
|
27
|
+
(cli_provided_parameters1, get_all_credentials_test_result_dict),
|
28
|
+
],
|
29
|
+
)
|
30
|
+
def test_get_all_credentials(parameters, test_value_dict, mocker):
|
31
|
+
pProfiles = parameters["pProfiles"]
|
32
|
+
pRegionList = parameters["pRegionList"]
|
33
|
+
pSkipProfiles = parameters["pSkipProfiles"]
|
34
|
+
pSkipAccounts = parameters["pSkipAccounts"]
|
35
|
+
pAccountList = parameters["pAccountList"]
|
36
|
+
pTiming = parameters["pTiming"]
|
37
|
+
pRootOnly = parameters["pRootOnly"]
|
38
|
+
pRoleList = parameters["pRoleList"]
|
39
|
+
test_data = {"FunctionName": "get_all_credentials", "AccountSpecific": True, "RegionSpecific": True}
|
40
|
+
_amend_make_api_call(test_data, test_value_dict, mocker)
|
41
|
+
|
42
|
+
# if isinstance(test_value, Exception):
|
43
|
+
# print("Expected Error...")
|
44
|
+
# with pytest.raises(type(test_value)) as error:
|
45
|
+
# get_all_credentials(pProfiles, pTiming, pSkipProfiles, pSkipAccounts, pRootOnly, pAccountList, pRegionList, pRoleList)
|
46
|
+
# result = error
|
47
|
+
# else:
|
48
|
+
result = get_all_credentials(
|
49
|
+
pProfiles, pTiming, pSkipProfiles, pSkipAccounts, pRootOnly, pAccountList, pRegionList, pRoleList
|
50
|
+
)
|
51
|
+
for cred in result:
|
52
|
+
assert cred["Success"]
|
53
|
+
print("Result:", result)
|
54
|
+
|
55
|
+
return result
|