Skip to content

Commit 2ce27d7

Browse files
committed
feat(services): add new service rds cluster snapshot
1 parent bcdfe7e commit 2ce27d7

19 files changed

Lines changed: 391 additions & 2 deletions

src/enums/schemasMap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export default {
7878
[services.vpnGateway]: 'awsVpnGateway',
7979
[services.sqs]: 'awsSqs',
8080
[services.rdsCluster]: 'awsRdsCluster',
81+
[services.rdsClusterSnapshot]: 'awsRdsClusterSnapshot',
8182
[services.rdsDbInstance]: 'awsRdsDbInstance',
8283
[services.redshiftCluster]: 'awsRedshiftCluster',
8384
[services.route53HostedZone]: 'awsRoute53HostedZone',

src/enums/serviceAliases.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export default {
5050
[services.networkInterface]: 'networkInterfaces',
5151
[services.organization]: 'organizations',
5252
[services.rdsCluster]: 'rdsClusters',
53+
[services.rdsClusterSnapshot]: 'rdsClusterSnapshots',
5354
[services.rdsDbInstance]: 'rdsDbInstances',
5455
[services.redshiftCluster]: 'redshiftClusters',
5556
[services.route53HostedZone]: 'route53HostedZones',

src/enums/serviceMap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ import DmsReplicationInstance from '../services/dmsReplicationInstance'
9393
import SageMakerNotebookInstance from '../services/sageMakerNotebookInstance'
9494
import SystemsManagerInstance from '../services/systemsManagerInstance'
9595
import SystemsManagerDocument from '../services/systemsManagerDocument'
96+
import RdsClusterSnapshot from '../services/rdsClusterSnapshot'
9697

9798
/**
9899
* serviceMap is an object that contains all currently supported services for AWS
@@ -157,6 +158,7 @@ export default {
157158
[services.vpc]: VPC,
158159
[services.sqs]: SQS,
159160
[services.rdsCluster]: RDSCluster,
161+
[services.rdsClusterSnapshot]: RdsClusterSnapshot,
160162
[services.rdsDbInstance]: RDSDbInstance,
161163
[services.redshiftCluster]: RedshiftCluster,
162164
[services.route53HostedZone]: Route53HostedZone,

src/enums/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export default {
6868
networkInterface: 'networkInterface',
6969
organization: 'organization',
7070
rdsCluster: 'rdsCluster',
71+
rdsClusterSnapshot: 'rdsClusterSnapshot',
7172
rdsDbInstance: 'rdsDbInstance',
7273
redshiftCluster: 'redshiftCluster',
7374
route53HostedZone: 'route53HostedZone',

src/services/account/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ type awsAccount @key(fields: "id") {
7070
networkInterfaces: [awsNetworkInterface]
7171
organizations: [awsOrganization]
7272
rdsClusters: [awsRdsCluster]
73+
rdsClusterSnapshots: [awsRdsClusterSnapshot]
7374
rdsDbInstances: [awsRdsDbInstance]
7475
redshiftClusters: [awsRedshiftCluster]
7576
route53HostedZones: [awsRoute53HostedZone]

src/services/kms/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ type awsKms @key(fields: "id"){
2929
elasticSearchDomains: [awsElasticSearchDomain] @hasInverse(field: kms)
3030
dmsReplicationInstances: [awsDmsReplicationInstance] @hasInverse(field: kms)
3131
sageMakerNotebookInstances: [awsSageMakerNotebookInstance] @hasInverse(field: kms)
32+
rdsClusterSnapshots: [awsRdsClusterSnapshot] @hasInverse(field: kms)
3233
}

src/services/rdsCluster/connections.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { SecurityGroup } from 'aws-sdk/clients/ec2'
44
import { DBInstance, DBCluster } from 'aws-sdk/clients/rds'
55

66
import services from '../../enums/services'
7+
import { RawAwsRdsClusterSnapshot } from '../rdsClusterSnapshot/data'
78

89
export default ({
910
service,
@@ -27,7 +28,7 @@ export default ({
2728
)
2829

2930
/**
30-
* Find instances
31+
* Find rds db instances
3132
*/
3233
const instances: {
3334
name: string
@@ -51,6 +52,30 @@ export default ({
5152
}
5253
}
5354

55+
/**
56+
* Find cluster snapshots
57+
*/
58+
const snapshots: {
59+
name: string
60+
data: { [property: string]: RawAwsRdsClusterSnapshot[] }
61+
} = data.find(({ name }) => name === services.rdsClusterSnapshot)
62+
63+
if (snapshots?.data?.[region]) {
64+
const dataInRegion: RawAwsRdsClusterSnapshot[] = snapshots.data[region].filter(
65+
({ DBClusterIdentifier }: RawAwsRdsClusterSnapshot) => DBClusterIdentifier === clusterId
66+
)
67+
if (!isEmpty(dataInRegion)) {
68+
for (const snapshot of dataInRegion) {
69+
connections.push({
70+
id: snapshot.DBClusterSnapshotIdentifier,
71+
resourceType: services.rdsClusterSnapshot,
72+
relation: 'child',
73+
field: 'snapshots',
74+
})
75+
}
76+
}
77+
}
78+
5479
/**
5580
* Find SecurityGroups
5681
*/

src/services/rdsCluster/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type awsRdsCluster @key(fields: "arn") {
3434
globalWriteForwardingRequested: Boolean @search
3535
tags: [awsRawTag]
3636
instances: [awsRdsDbInstance] @hasInverse(field: cluster)
37+
snapshots: [awsRdsClusterSnapshot] @hasInverse(field: cluster)
3738
securityGroups: [awsSecurityGroup] @hasInverse(field: rdsCluster)
3839
appSync: [awsAppSync] @hasInverse(field: rdsCluster)
3940
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { ServiceConnection } from '@cloudgraph/sdk'
2+
import { isEmpty } from 'lodash'
3+
import { RawAwsRdsClusterSnapshot } from './data'
4+
import services from '../../enums/services'
5+
6+
export default ({
7+
service,
8+
data,
9+
region,
10+
}: {
11+
account: string
12+
service: RawAwsRdsClusterSnapshot
13+
data: { name: string; data: { [property: string]: any[] } }[]
14+
region: string
15+
}): {
16+
[property: string]: ServiceConnection[]
17+
} => {
18+
const { DBClusterSnapshotIdentifier, KmsKeyId } = service
19+
const connections: ServiceConnection[] = []
20+
21+
/**
22+
* Find KMS
23+
*/
24+
const kmsKeys = data.find(({ name }) => name === services.kms)
25+
if (kmsKeys?.data?.[region]) {
26+
const kmsKeyInRegion = kmsKeys.data[region].filter(kmsKey => kmsKey.Arn === KmsKeyId)
27+
if (!isEmpty(kmsKeyInRegion)) {
28+
for (const kms of kmsKeyInRegion) {
29+
connections.push({
30+
id: kms.KeyId,
31+
resourceType: services.kms,
32+
relation: 'child',
33+
field: 'kms',
34+
})
35+
}
36+
}
37+
}
38+
39+
const result = {
40+
[DBClusterSnapshotIdentifier]: connections,
41+
}
42+
return result
43+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Config } from 'aws-sdk/lib/config'
2+
import { groupBy, isEmpty } from 'lodash'
3+
import RDS from 'aws-sdk/clients/rds'
4+
import { convertToPromise, fetchAllPaginatedData } from '../../utils/fetchUtils'
5+
import { initTestEndpoint } from '../../utils'
6+
import ErrorLog from '../../utils/errorLog'
7+
import { convertAwsTagsToTagMap } from '../../utils/format'
8+
import { TagMap, AwsTag } from '../../types'
9+
10+
const serviceName = 'rdsClusterSnapshot'
11+
const endpoint = initTestEndpoint(serviceName)
12+
const errorLog = new ErrorLog(serviceName)
13+
14+
export interface RawAwsRdsClusterSnapshot extends RDS.DBClusterSnapshot {
15+
region: string
16+
attributes: RDS.DBClusterSnapshotAttributeList
17+
Tags: TagMap
18+
}
19+
20+
/**
21+
* RdsClusterSnapshot
22+
*/
23+
24+
export default async ({
25+
regions,
26+
config,
27+
}: {
28+
regions: string
29+
config: Config
30+
}): Promise<{ [region: string]: RawAwsRdsClusterSnapshot[] }> => {
31+
const result: RawAwsRdsClusterSnapshot[] = []
32+
33+
const activeRegions = regions.split(',')
34+
35+
for (const region of activeRegions) {
36+
const client = new RDS({ ...config, region, endpoint })
37+
let rdsClusterSnapshotData: RDS.DBClusterSnapshot[]
38+
try {
39+
rdsClusterSnapshotData = await fetchAllPaginatedData({
40+
getResourcesFn: convertToPromise({
41+
sdkContext: client,
42+
fnName: 'describeDBClusterSnapshots',
43+
}),
44+
accessor: '',
45+
})
46+
} catch (err) {
47+
errorLog.generateAwsErrorLog({ functionName: 'describeDBClusterSnapshots', err })
48+
}
49+
50+
if (!isEmpty(rdsClusterSnapshotData)) {
51+
for (const snapshot of rdsClusterSnapshotData) {
52+
let snapshotAttributes: RDS.DBClusterSnapshotAttributeList
53+
try {
54+
const attributeResponse = await client
55+
.describeDBClusterSnapshotAttributes({
56+
DBClusterSnapshotIdentifier: snapshot.DBClusterSnapshotIdentifier,
57+
})
58+
.promise()
59+
snapshotAttributes =
60+
attributeResponse?.DBClusterSnapshotAttributesResult?.DBClusterSnapshotAttributes
61+
} catch (err) {
62+
errorLog.generateAwsErrorLog({ functionName: 'describeDBClusterSnapshotAttributes', err })
63+
}
64+
result.push({ ...snapshot, Tags: convertAwsTagsToTagMap(snapshot?.TagList as AwsTag[]), attributes: snapshotAttributes, region })
65+
}
66+
}
67+
}
68+
69+
errorLog.reset()
70+
return groupBy(result, 'region')
71+
}

0 commit comments

Comments
 (0)