Skip to content

Commit b8f895b

Browse files
committed
Add support for new resources:
- apigatewayv2 - cloudfront distribution - ACM - redshift cluster - SQS - ECS Fix view bugs, update data types to be more useful
1 parent f57df8c commit b8f895b

127 files changed

Lines changed: 18625 additions & 4619 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

goldfig/aws/acm.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from dis import dis
2+
import logging
3+
from typing import Any, Dict, Generator, Tuple
4+
5+
from goldfig.aws.fetch import ServiceProxy
6+
from goldfig.aws.svc import make_import_to_db, make_import_with_pool
7+
8+
_log = logging.getLogger(__name__)
9+
10+
11+
def _import_certificate(proxy: ServiceProxy, summary: Dict) -> Dict[str, Any]:
12+
arn = summary['CertificateArn']
13+
certificate = proxy.get('describe_certificate',
14+
CertificateArn=arn)['Certificate']
15+
tags_resp = proxy.list('list_tags_for_certificate', CertificateArn=arn)
16+
if tags_resp is not None:
17+
certificate['Tags'] = tags_resp[1]['Tags']
18+
return certificate
19+
20+
21+
def _import_certificates(proxy: ServiceProxy, region: str):
22+
certificates_resp = proxy.list('list_certificates')
23+
if certificates_resp is not None:
24+
certificates = certificates_resp[1]['CertificateSummaryList']
25+
for certificate in certificates:
26+
yield 'Certificate', _import_certificate(proxy, certificate)
27+
28+
29+
def _import_acm_region(proxy: ServiceProxy,
30+
region: str) -> Generator[Tuple[str, Any], None, None]:
31+
_log.info(f'importing Certificates')
32+
yield from _import_certificates(proxy, region)
33+
34+
35+
import_account_acm_region_to_db = make_import_to_db('acm', _import_acm_region)
36+
37+
import_account_acm_region_with_pool = make_import_with_pool(
38+
'acm', _import_acm_region)

goldfig/aws/apigatewayv2.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from dis import dis
2+
import logging
3+
from typing import Any, Dict, Generator, Tuple
4+
5+
from goldfig.aws.fetch import ServiceProxy
6+
from goldfig.aws.svc import make_import_to_db, make_import_with_pool
7+
8+
_log = logging.getLogger(__name__)
9+
10+
ApiResources = ['stages', 'routes', 'integrations', 'models']
11+
12+
13+
def _import_api(proxy: ServiceProxy, api: Dict) -> Dict[str, Any]:
14+
api_id = api['ApiId']
15+
for resource in ApiResources:
16+
resp = proxy.list('get_' + resource, ApiId=api_id)
17+
if resp is not None:
18+
api[resource.capitalize()] = resp[1]['Items']
19+
return api
20+
21+
22+
def _import_apis(proxy: ServiceProxy, region: str):
23+
apis_resp = proxy.list('get_apis')
24+
if apis_resp is not None:
25+
apis = apis_resp[1]['Items']
26+
for api in apis:
27+
yield 'Api', _import_api(proxy, api)
28+
29+
30+
def _import_apigatewayv2_region(
31+
proxy: ServiceProxy,
32+
region: str) -> Generator[Tuple[str, Any], None, None]:
33+
_log.info(f'importing Apis')
34+
yield from _import_apis(proxy, region)
35+
36+
37+
import_account_apigatewayv2_region_to_db = make_import_to_db(
38+
'apigatewayv2', _import_apigatewayv2_region)
39+
40+
import_account_apigatewayv2_region_with_pool = make_import_with_pool(
41+
'apigatewayv2', _import_apigatewayv2_region)

goldfig/aws/cloudfront.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from dis import dis
2+
import logging
3+
from typing import Any, Dict, Generator, Tuple
4+
5+
from goldfig.aws.fetch import ServiceProxy
6+
from goldfig.aws.svc import make_import_to_db, make_import_with_pool
7+
8+
_log = logging.getLogger(__name__)
9+
10+
11+
def _import_distribution(proxy: ServiceProxy, summary: Dict) -> Dict[str, Any]:
12+
arn = summary['ARN']
13+
distribution_id = summary['Id']
14+
distribution = proxy.get('get_distribution', Id=distribution_id)
15+
config = proxy.get('get_distribution_config', Id=distribution_id)
16+
distribution.update(config)
17+
tags_resp = proxy.list('list_tags_for_resource', Resource=arn)
18+
if tags_resp is not None:
19+
distribution['Tags'] = tags_resp[1]['Tags']
20+
return distribution
21+
22+
23+
def _import_distributions(proxy: ServiceProxy, region: str):
24+
distributions_resp = proxy.list('list_distributions')
25+
if distributions_resp is not None:
26+
distributions = distributions_resp[1]['DistributionList']['Items']
27+
for summary in distributions:
28+
yield 'Distribution', _import_distribution(proxy, summary)
29+
30+
31+
def _import_cloudfront_region(
32+
proxy: ServiceProxy,
33+
region: str) -> Generator[Tuple[str, Any], None, None]:
34+
_log.info(f'importing distributions')
35+
yield from _import_distributions(proxy, region)
36+
37+
38+
import_account_cloudfront_region_to_db = make_import_to_db(
39+
'cloudfront', _import_cloudfront_region)
40+
41+
import_account_cloudfront_region_with_pool = make_import_with_pool(
42+
'cloudfront', _import_cloudfront_region)

goldfig/aws/ecs.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import logging
2+
from typing import Any, Dict, Generator, Tuple
3+
4+
from goldfig.aws.fetch import ServiceProxy
5+
from goldfig.aws.svc import make_import_to_db, make_import_with_pool
6+
from goldfig.error import GFInternal
7+
8+
_log = logging.getLogger(__name__)
9+
10+
11+
def _import_cluster(proxy: ServiceProxy, cluster_arn: str) -> Dict[str, Any]:
12+
clusters_resp = proxy.list(
13+
'describe_clusters',
14+
clusters=[cluster_arn],
15+
include=["ATTACHMENTS", "SETTINGS", "STATISTICS", "TAGS"])
16+
if clusters_resp is None:
17+
raise GFInternal(f'Failed to fetch ecs cluster {cluster_arn}')
18+
cluster_list = clusters_resp[1].get('clusters', [])
19+
if len(cluster_list) != 1:
20+
raise GFInternal(
21+
f'Wrong number of clusters for {cluster_arn} {clusters_resp}')
22+
cluster = cluster_list[0]
23+
return cluster
24+
25+
26+
def _import_service(proxy: ServiceProxy, cluster_arn: str, service_arn: str):
27+
services_resp = proxy.list('describe_services',
28+
cluster=cluster_arn,
29+
services=[service_arn],
30+
include=['TAGS'])
31+
if services_resp is None:
32+
raise GFInternal(f'Failed to fetch ecs service {service_arn}')
33+
service_list = services_resp[1].get('services', [])
34+
if len(service_list) != 1:
35+
raise GFInternal(
36+
f'Wrong number of services for {service_arn} {services_resp}')
37+
service = service_list[0]
38+
return service
39+
40+
41+
def _import_services(proxy: ServiceProxy, cluster_arn: str):
42+
services_resp = proxy.list('list_services', cluster=cluster_arn)
43+
if services_resp is not None:
44+
service_arns = services_resp[1].get('serviceArns', [])
45+
for service_arn in service_arns:
46+
yield 'Service', _import_service(proxy, cluster_arn, service_arn)
47+
48+
49+
def _import_task(proxy: ServiceProxy, cluster_arn: str, task_arn: str):
50+
tasks_resp = proxy.list('describe_tasks',
51+
cluster=cluster_arn,
52+
tasks=[task_arn],
53+
include=['TAGS'])
54+
if tasks_resp is None:
55+
raise GFInternal(f'Failed to fetch ecs task {task_arn}')
56+
task_list = tasks_resp[1].get('tasks', [])
57+
if len(task_list) != 1:
58+
raise GFInternal(f'Wrong number of tasks for {task_arn} {tasks_resp}')
59+
task = task_list[0]
60+
return task
61+
62+
63+
def _import_tasks(proxy: ServiceProxy, cluster_arn: str):
64+
tasks_resp = proxy.list('list_tasks', cluster=cluster_arn)
65+
if tasks_resp is not None:
66+
task_arns = tasks_resp[1].get('taskArns', [])
67+
for task_arn in task_arns:
68+
yield 'Task', _import_task(proxy, cluster_arn, task_arn)
69+
70+
71+
def _import_clusters(proxy: ServiceProxy, region: str):
72+
clusters_resp = proxy.list('list_clusters')
73+
if clusters_resp is not None:
74+
cluster_arns = clusters_resp[1].get('clusterArns', [])
75+
for cluster_arn in cluster_arns:
76+
yield 'Cluster', _import_cluster(proxy, cluster_arn)
77+
yield from _import_services(proxy, cluster_arn)
78+
yield from _import_tasks(proxy, cluster_arn)
79+
80+
81+
def _import_task_definition(proxy: ServiceProxy, definition_arn: str):
82+
definition = proxy.get('describe_task_definition',
83+
taskDefinition=definition_arn,
84+
include=['TAGS'])['taskDefinition']
85+
return definition
86+
87+
88+
def _import_task_definitions(proxy: ServiceProxy):
89+
definitions_resp = proxy.list('list_task_definitions')
90+
if definitions_resp is not None:
91+
definition_arns = definitions_resp[1].get('taskDefinitionArns', [])
92+
for definition_arn in definition_arns:
93+
yield 'TaskDefinition', _import_task_definition(proxy, definition_arn)
94+
95+
96+
def _import_ecs_region(proxy: ServiceProxy,
97+
region: str) -> Generator[Tuple[str, Any], None, None]:
98+
_log.info(f'importing ecs clusters')
99+
yield from _import_clusters(proxy, region)
100+
yield from _import_task_definitions(proxy)
101+
102+
103+
import_account_ecs_region_to_db = make_import_to_db('ecs', _import_ecs_region)
104+
105+
import_account_ecs_region_with_pool = make_import_with_pool(
106+
'ecs', _import_ecs_region)

goldfig/aws/fetch.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ def list(self, key: str, kwargs) -> Optional[Tuple[str, Any]]:
159159
result = {
160160
result_key: full_result[result_key]
161161
for result_key in output.members.keys()
162+
if result_key in full_result
162163
}
163164
return resource_name, result
164165
except KeyError as e:

goldfig/aws/importer.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,25 @@
66

77
from goldfig import collect_exceptions, PathStack
88
from goldfig.aws import ProxyBuilder
9+
from goldfig.aws.acm import import_account_acm_region_to_db, import_account_acm_region_with_pool
10+
from goldfig.aws.apigatewayv2 import import_account_apigatewayv2_region_to_db, import_account_apigatewayv2_region_with_pool
911
from goldfig.aws.iam import import_account_iam_to_db, import_account_iam_with_pool
1012
from goldfig.aws.ec2 import import_account_ec2_region_to_db, import_account_ec2_region_with_pool
13+
from goldfig.aws.ecs import import_account_ecs_region_to_db, import_account_ecs_region_with_pool
1114
from goldfig.aws.elb import import_account_elb_region_to_db, import_account_elb_region_with_pool
1215
from goldfig.aws.s3 import import_account_s3_to_db, import_account_s3_with_pool
1316
from goldfig.aws.kms import import_account_kms_region_to_db, import_account_kms_region_with_pool
1417
from goldfig.aws.lambdax import import_account_lambda_region_to_db, import_account_lambda_region_with_pool
1518
from goldfig.aws.logs import import_account_logs_region_to_db, import_account_logs_region_with_pool
19+
from goldfig.aws.cloudfront import import_account_cloudfront_region_to_db, import_account_cloudfront_region_with_pool
1620
from goldfig.aws.cloudtrail import import_account_cloudtrail_region_to_db, import_account_cloudtrail_region_with_pool
1721
from goldfig.aws.cloudwatch import import_account_cloudwatch_region_to_db, import_account_cloudwatch_region_with_pool
1822
from goldfig.aws.config import import_account_config_region_to_db, import_account_config_region_with_pool
1923
from goldfig.aws.region import RegionCache
2024
from goldfig.aws.rds import import_account_rds_region_to_db, import_account_rds_region_with_pool
25+
from goldfig.aws.redshift import import_account_redshift_region_to_db, import_account_redshift_region_with_pool
2126
from goldfig.aws.sns import import_account_sns_region_to_db, import_account_sns_region_with_pool
27+
from goldfig.aws.sqs import import_account_sqs_region_to_db, import_account_sqs_region_with_pool
2228
from goldfig.models import ImportJob, ProviderCredential
2329

2430

@@ -32,6 +38,10 @@ def run_single_session(db: Session, import_job_id: int,
3238
import_account_ec2_region_to_db(db, import_job_id, region, proxy_builder)
3339
db.flush()
3440

41+
for region in region_cache.regions_for_service('ecs'):
42+
import_account_ecs_region_to_db(db, import_job_id, region, proxy_builder)
43+
db.flush()
44+
3545
for region in region_cache.regions_for_service('kms'):
3646
import_account_kms_region_to_db(db, import_job_id, region, proxy_builder)
3747
db.flush()
@@ -70,6 +80,29 @@ def run_single_session(db: Session, import_job_id: int,
7080
import_account_sns_region_to_db(db, import_job_id, region, proxy_builder)
7181
db.flush()
7282

83+
for region in region_cache.regions_for_service('sqs'):
84+
import_account_sqs_region_to_db(db, import_job_id, region, proxy_builder)
85+
db.flush()
86+
87+
for region in region_cache.regions_for_service('cloudfront'):
88+
import_account_cloudfront_region_to_db(db, import_job_id, region,
89+
proxy_builder)
90+
db.flush()
91+
92+
for region in region_cache.regions_for_service('apigatewayv2'):
93+
import_account_apigatewayv2_region_to_db(db, import_job_id, region,
94+
proxy_builder)
95+
db.flush()
96+
97+
for region in region_cache.regions_for_service('acm'):
98+
import_account_acm_region_to_db(db, import_job_id, region, proxy_builder)
99+
db.flush()
100+
101+
for region in region_cache.regions_for_service('redshift'):
102+
import_account_redshift_region_to_db(db, import_job_id, region,
103+
proxy_builder)
104+
db.flush()
105+
73106
import_account_s3_to_db(db, import_job_id, proxy_builder)
74107

75108

@@ -92,6 +125,11 @@ def run_parallel_session(region_cache: RegionCache,
92125
import_job.id, region, ps,
93126
accounts)
94127

128+
for region in region_cache.regions_for_service('ecs'):
129+
results += import_account_ecs_region_with_pool(pool, proxy_builder_args,
130+
import_job.id, region, ps,
131+
accounts)
132+
95133
for region in region_cache.regions_for_service('kms'):
96134
results += import_account_kms_region_with_pool(pool, proxy_builder_args,
97135
import_job.id, region, ps,
@@ -133,6 +171,27 @@ def run_parallel_session(region_cache: RegionCache,
133171
import_job.id, region, ps,
134172
accounts)
135173

174+
for region in region_cache.regions_for_service('sqs'):
175+
results += import_account_sqs_region_with_pool(pool, proxy_builder_args,
176+
import_job.id, region, ps,
177+
accounts)
178+
179+
for region in region_cache.regions_for_service('cloudfront'):
180+
results += import_account_cloudfront_region_with_pool(
181+
pool, proxy_builder_args, import_job.id, region, ps, accounts)
182+
183+
for region in region_cache.regions_for_service('apigatewayv2'):
184+
results += import_account_apigatewayv2_region_with_pool(
185+
pool, proxy_builder_args, import_job.id, region, ps, accounts)
186+
187+
for region in region_cache.regions_for_service('acm'):
188+
results += import_account_acm_region_with_pool(pool, proxy_builder_args,
189+
import_job.id, region, ps,
190+
accounts)
191+
192+
for region in region_cache.regions_for_service('redshift'):
193+
results += import_account_redshift_region_with_pool(
194+
pool, proxy_builder_args, import_job.id, region, ps, accounts)
136195
f.wait(results)
137196
# raise any exceptions
138197
return collect_exceptions(results)

goldfig/aws/redshift.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from dis import dis
2+
import logging
3+
from typing import Any, Dict, Generator, Tuple
4+
5+
from goldfig.aws.fetch import ServiceProxy
6+
from goldfig.aws.svc import make_import_to_db, make_import_with_pool
7+
8+
_log = logging.getLogger(__name__)
9+
10+
11+
def _import_cluster(proxy: ServiceProxy, cluster: Dict) -> Dict[str, Any]:
12+
return cluster
13+
14+
15+
def _import_clusters(proxy: ServiceProxy, region: str):
16+
clusters_resp = proxy.list('describe_clusters')
17+
if clusters_resp is not None:
18+
clusters = clusters_resp[1]['Clusters']
19+
for cluster in clusters:
20+
yield 'Cluster', _import_cluster(proxy, cluster)
21+
22+
23+
def _import_redshift_region(
24+
proxy: ServiceProxy,
25+
region: str) -> Generator[Tuple[str, Any], None, None]:
26+
_log.info(f'importing Redshift Clusters')
27+
yield from _import_clusters(proxy, region)
28+
29+
30+
import_account_redshift_region_to_db = make_import_to_db(
31+
'redshift', _import_redshift_region)
32+
33+
import_account_redshift_region_with_pool = make_import_with_pool(
34+
'redshift', _import_redshift_region)

0 commit comments

Comments
 (0)