Skip to content

Commit a21dc3d

Browse files
author
Marco Franceschi
authored
Merge pull request #154 from cloudgraphdev/feat/EP-3204
feat: Added docdb service
2 parents b292e03 + 44e7659 commit a21dc3d

File tree

12 files changed

+319
-1
lines changed

12 files changed

+319
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ CloudGraph AWS Provider will ask you what regions you would like to crawl and wi
102102
| configurationRule | |
103103
| customerGateway | vpnConnection |
104104
| dynamodb | appSync, iamRole, kms |
105+
| docdbCluster | |
105106
| dmsReplicationInstance | securityGroup, subnet, vpc, kms |
106107
| ebs | asg, ec2, emrInstance, ebsSnapshot |
107108
| ebsSnapshot | ebs, kms |

src/enums/schemasMap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export default {
3434
[services.customerGateway]: 'awsCustomerGateway',
3535
[services.dmsReplicationInstance]: 'awsDmsReplicationInstance',
3636
[services.dynamodb]: 'awsDynamoDbTable',
37+
[services.docdbCluster]: 'awsDocdbCluster',
3738
[services.ebs]: 'awsEbs',
3839
[services.ebsSnapshot]: 'awsEbsSnapshot',
3940
[services.ec2Instance]: 'awsEc2',

src/enums/serviceMap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import ConfigurationRule from '../services/configurationRule'
3232
import CustomerGateway from '../services/customerGateway'
3333
import DmsReplicationInstance from '../services/dmsReplicationInstance'
3434
import DynamoDB from '../services/dynamodb'
35+
import DocDBCluster from '../services/docdbCluster'
3536
import EBS from '../services/ebs'
3637
import EBSSnapshot from '../services/ebsSnapshot'
3738
import EC2 from '../services/ec2'
@@ -194,6 +195,7 @@ export default {
194195
[services.emrStep]: EmrStep,
195196
[services.dmsReplicationInstance]: DmsReplicationInstance,
196197
[services.dynamodb]: DynamoDB,
198+
[services.docdbCluster]: DocDBCluster,
197199
[services.igw]: AwsInternetGateway,
198200
[services.iot]: IotThingAttribute,
199201
[services.kinesisFirehose]: AwsKinesisFirehose,

src/enums/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default {
3535
customerGateway: 'customerGateway',
3636
dmsReplicationInstance: 'dmsReplicationInstance',
3737
dynamodb: 'dynamodb',
38+
docdbCluster: 'docdbCluster',
3839
ebs: 'ebs',
3940
ebsSnapshot: 'ebsSnapshot',
4041
ec2Instance: 'ec2Instance',

src/properties/logger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ export default {
305305
lookingforRdsClusters: 'Looking for RDS Clusters...',
306306
creatingRdsInstance: (num: number): string => `Creating RDS Instance #${num}`,
307307
fetchedRdsClusters: (num: number): string => `Fetched ${num} RDS Clusters`,
308+
fetchedDocdbClusters: (num: number): string => `Fetched ${num} DocDB Clusters`,
308309
fetchedRdsGlobalClusters: (num: number): string =>
309310
`Fetched ${num} RDS Global Clusters`,
310311
fetchedRdsInstances: (num: number): string =>

src/services/account/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type awsAccount implements awsOptionalService @key(fields: "id") {
3333
customerGateway: [awsCustomerGateway]
3434
dmsReplicationInstances: [awsDmsReplicationInstance]
3535
dynamodb: [awsDynamoDbTable]
36+
docdbCluster: [awsDocdbCluster]
3637
ebs: [awsEbs]
3738
ec2Instances: [awsEc2]
3839
ecr: [awsEcr]

src/services/docdbCluster/data.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import CloudGraph from '@cloudgraph/sdk'
2+
import DOCDB, {
3+
DBCluster,
4+
TagListMessage,
5+
DescribeDBClustersMessage,
6+
DBClusterMessage,
7+
DBSubnetGroup,
8+
DBSubnetGroupMessage,
9+
} from 'aws-sdk/clients/docdb'
10+
import { AWSError } from 'aws-sdk/lib/error'
11+
import groupBy from 'lodash/groupBy'
12+
import isEmpty from 'lodash/isEmpty'
13+
import { Config } from 'aws-sdk/lib/config'
14+
import awsLoggerText from '../../properties/logger'
15+
import { TagMap, AwsTag } from '../../types'
16+
import { convertAwsTagsToTagMap } from '../../utils/format'
17+
import AwsErrorLog from '../../utils/errorLog'
18+
import { initTestEndpoint } from '../../utils'
19+
20+
const lt = { ...awsLoggerText }
21+
const { logger } = CloudGraph
22+
const serviceName = 'DOC DB cluster'
23+
const errorLog = new AwsErrorLog(serviceName)
24+
const endpoint = initTestEndpoint(serviceName)
25+
26+
const listClustersForRegion = async (docdb: DOCDB): Promise<DBCluster[]> =>
27+
new Promise<DBCluster[]>(resolve => {
28+
const clusterList: DBCluster[] = []
29+
const descClustersOpts: DescribeDBClustersMessage = {}
30+
const listAllClusters = (token?: string): void => {
31+
if (token) {
32+
descClustersOpts.Marker = token
33+
}
34+
try {
35+
docdb.describeDBClusters(
36+
descClustersOpts,
37+
(err: AWSError, data: DBClusterMessage) => {
38+
const { Marker, DBClusters = [] } = data || {}
39+
if (err) {
40+
errorLog.generateAwsErrorLog({
41+
functionName: 'docdb:describeDBClusters',
42+
err,
43+
})
44+
}
45+
46+
clusterList.push(...DBClusters)
47+
48+
if (Marker) {
49+
listAllClusters(Marker)
50+
} else {
51+
resolve(clusterList)
52+
}
53+
}
54+
)
55+
} catch (error) {
56+
resolve([])
57+
}
58+
}
59+
listAllClusters()
60+
})
61+
62+
const describeDBSubnetGroups = async (
63+
docdb: DOCDB,
64+
DBSubnetGroupName: string
65+
): Promise<DBSubnetGroup[]> =>
66+
new Promise(resolve => {
67+
try {
68+
docdb.describeDBSubnetGroups(
69+
{ DBSubnetGroupName },
70+
(err: AWSError, data: DBSubnetGroupMessage) => {
71+
if (err) {
72+
errorLog.generateAwsErrorLog({
73+
functionName: 'docdb:describeDBSubnetGroups',
74+
err,
75+
})
76+
return resolve([])
77+
}
78+
if (!isEmpty(data)) {
79+
resolve(data.DBSubnetGroups)
80+
}
81+
}
82+
)
83+
} catch (error) {
84+
resolve([])
85+
}
86+
})
87+
88+
export interface RawAwsDocDBCluster extends DBCluster {
89+
DbSubnetGroups: DBSubnetGroup[]
90+
Tags?: TagMap
91+
region: string
92+
}
93+
94+
export default async ({
95+
regions,
96+
config,
97+
}: {
98+
regions: string
99+
config: Config
100+
}): Promise<{ [property: string]: RawAwsDocDBCluster[] }> =>
101+
new Promise(async resolve => {
102+
const docDBData: RawAwsDocDBCluster[] = []
103+
const regionPromises = []
104+
105+
// Get all the clusters for the region
106+
regions.split(',').map(region => {
107+
const regionPromise = new Promise<void>(async resolveRegion => {
108+
const docdb = new DOCDB({ ...config, region, endpoint })
109+
const clusters = await listClustersForRegion(docdb)
110+
111+
if (!isEmpty(clusters)) {
112+
docDBData.push(
113+
...(await Promise.all(
114+
clusters.map(async cluster => ({
115+
...cluster,
116+
DbSubnetGroups: await describeDBSubnetGroups(
117+
docdb,
118+
cluster.DBSubnetGroup
119+
),
120+
region,
121+
}))
122+
))
123+
)
124+
}
125+
resolveRegion()
126+
})
127+
regionPromises.push(regionPromise)
128+
})
129+
130+
await Promise.all(regionPromises)
131+
logger.debug(lt.fetchedDocdbClusters(docDBData.length))
132+
errorLog.reset()
133+
134+
resolve(groupBy(docDBData, 'region'))
135+
})
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { RawAwsDocDBCluster } from './data'
2+
import { AwsDocdbCluster } from '../../types/generated'
3+
import { formatTagsFromMap } from '../../utils/format'
4+
5+
export default ({
6+
service,
7+
account,
8+
region,
9+
}: {
10+
service: RawAwsDocDBCluster
11+
account: string
12+
region: string
13+
}): AwsDocdbCluster => {
14+
const {
15+
AvailabilityZones = [],
16+
BackupRetentionPeriod: backupRetentionPeriod,
17+
DBClusterIdentifier: dBClusterIdentifier,
18+
DBClusterParameterGroup: dBClusterParameterGroup,
19+
DBSubnetGroup: dBSubnetGroup,
20+
Status: status,
21+
PercentProgress: percentProgress,
22+
EarliestRestorableTime: earliestRestorableTime,
23+
Endpoint: endpoint,
24+
ReaderEndpoint: readerEndpoint,
25+
MultiAZ: multiAZ,
26+
Engine: engine,
27+
EngineVersion: engineVersion,
28+
LatestRestorableTime: latestRestorableTime,
29+
Port: port,
30+
MasterUsername: masterUsername,
31+
PreferredBackupWindow: preferredBackupWindow,
32+
PreferredMaintenanceWindow: preferredMaintenanceWindow,
33+
ReplicationSourceIdentifier: replicationSourceIdentifier,
34+
ReadReplicaIdentifiers: readReplicaIdentifiers,
35+
DBClusterMembers = [],
36+
VpcSecurityGroups = [],
37+
HostedZoneId: hostedZoneId,
38+
StorageEncrypted: storageEncrypted,
39+
KmsKeyId: kmsKeyId,
40+
DbClusterResourceId: dbClusterResourceId,
41+
DBClusterArn: arn,
42+
CloneGroupId: cloneGroupId,
43+
ClusterCreateTime: clusterCreateTime,
44+
DeletionProtection: deletionProtection,
45+
} = service
46+
47+
const availabilityZones = AvailabilityZones.map(az => az)
48+
const dBClusterMembers = DBClusterMembers.map(dbinstance => dbinstance.DBInstanceIdentifier)
49+
const vpcSecurityGroups = VpcSecurityGroups.map(vpcsg => vpcsg.VpcSecurityGroupId)
50+
51+
return {
52+
id: arn,
53+
accountId: account,
54+
arn,
55+
region,
56+
availabilityZones,
57+
backupRetentionPeriod,
58+
dBClusterIdentifier,
59+
dBClusterParameterGroup,
60+
dBSubnetGroup,
61+
status,
62+
percentProgress,
63+
earliestRestorableTime: earliestRestorableTime?.toISOString(),
64+
endpoint,
65+
readerEndpoint,
66+
multiAZ,
67+
engine,
68+
engineVersion,
69+
latestRestorableTime: latestRestorableTime?.toISOString(),
70+
port,
71+
masterUsername,
72+
preferredBackupWindow,
73+
preferredMaintenanceWindow,
74+
replicationSourceIdentifier,
75+
readReplicaIdentifiers,
76+
dBClusterMembers,
77+
vpcSecurityGroups,
78+
hostedZoneId,
79+
storageEncrypted,
80+
kmsKeyId,
81+
dbClusterResourceId,
82+
cloneGroupId,
83+
clusterCreateTime: clusterCreateTime?.toISOString(),
84+
deletionProtection,
85+
}
86+
}

src/services/docdbCluster/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Service } from '@cloudgraph/sdk'
2+
import BaseService from '../base'
3+
import format from './format'
4+
import getData from './data'
5+
import mutation from './mutation'
6+
7+
export default class DOCDBCluster extends BaseService implements Service {
8+
format = format.bind(this)
9+
10+
getData = getData.bind(this)
11+
12+
mutation = mutation
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default `mutation($input: [AddawsDocdbClusterInput!]!) {
2+
addawsDocdbCluster(input: $input, upsert: true) {
3+
numUids
4+
}
5+
}`

0 commit comments

Comments
 (0)