Skip to content

Commit f93f4b3

Browse files
committed
Merge branch 'feature/CG-665-add-api-gateway' into 'main'
feat(apigateway): CG-665 add api gateway Closes CG-665 See merge request auto-cloud/cloudgraph/provider/cloudgraph-provider-gcp!46
2 parents 261c099 + 05ff0a5 commit f93f4b3

26 files changed

Lines changed: 629 additions & 2 deletions

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ CloudGraph GCP Provider will ask you what regions you would like to crawl and wi
6565
| Service | Relations |
6666
| ------------------------------------- | --------------------------------------------------------------------------------------------------- |
6767
| alertPolicy | project |
68+
| apiGatewayGateways | project, apiGatewayApis, apiGatewayApiConfigs |
69+
| apiGatewayApis | project, apiGatewayGateways |
70+
| apiGatewayApiConfigs | project, apiGatewayGateways |
6871
| apiKeys | project |
6972
| assets | project |
7073
| bigQueryDataset | project |

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
},
3434
"dependencies": {
3535
"@cloudgraph/sdk": "^0.11.0",
36+
"@google-cloud/api-gateway": "^1.2.1",
3637
"@google-cloud/asset": "^3.22.0",
3738
"@google-cloud/bigquery": "^5.10.0",
3839
"@google-cloud/bigquery-connection": "^1.5.1",

src/enums/relations.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import services from './services'
33
/**
44
* Set relations between services to data sharing
55
* The key of the object represents the parent or base service,
6-
* it might contain a array of dependant or childs that must be executed after the parent
6+
* it might contain an array of dependant or children that must be executed after the parent
77
*/
88
export default {
99
[services.storageBucket]: [services.iamPolicy],
@@ -14,4 +14,5 @@ export default {
1414
[services.kmsKeyRing]: [services.kmsCryptoKeys],
1515
[services.kmsCryptoKeys]: [services.iamPolicy],
1616
[services.bigQueryDataTransfer]: [services.bigQueryDataTransferRun],
17+
[services.apiGatewayApi]: [services.apiGatewayApiConfig],
1718
}

src/enums/schemasMap.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export default {
4747
[services.dataprocAutoscalingPolicy]: 'gcpDataprocAutoscalingPolicy',
4848
[services.dataprocJob]: 'gcpDataprocJob',
4949
[services.dataprocWorkflowTemplate]: 'gcpDataprocWorkflowTemplate',
50+
[services.apiGatewayGateway]: 'gcpApiGatewayGateway',
51+
[services.apiGatewayApi]: 'gcpApiGatewayApi',
52+
[services.apiGatewayApiConfig]: 'gcpApiGatewayApiConfig',
5053
[services.firestoreDatabase]: 'gcpFirestoreDatabase',
5154
tag: 'gcpTag',
5255
}

src/enums/serviceMap.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ import GcpDataprocCluster from '../services/dataprocCluster'
4242
import GcpDataprocAutoscalingPolicy from '../services/dataprocAutoscalingPolicy'
4343
import GcpDataprocJob from '../services/dataprocJob'
4444
import GcpDataprocWorkflowTemplate from '../services/dataprocWorkflowTemplate'
45+
import GcpApiGatewayGateway from '../services/apiGatewayGateway'
46+
import GcpApiGatewayApi from '../services/apiGatewayApi'
47+
import GcpApiGatewayApiConfig from '../services/apiGatewayApiConfig'
4548
import GcpFirestoreDatabase from '../services/firestore'
4649
import GcpLabel from '../services/label'
4750
import GcpTag from '../services/tag'
@@ -94,6 +97,9 @@ export default {
9497
[services.dataprocAutoscalingPolicy]: GcpDataprocAutoscalingPolicy,
9598
[services.dataprocJob]: GcpDataprocJob,
9699
[services.dataprocWorkflowTemplate]: GcpDataprocWorkflowTemplate,
100+
[services.apiGatewayGateway]: GcpApiGatewayGateway,
101+
[services.apiGatewayApi]: GcpApiGatewayApi,
102+
[services.apiGatewayApiConfig]: GcpApiGatewayApiConfig,
97103
[services.firestoreDatabase]: GcpFirestoreDatabase,
98104
label: GcpLabel,
99105
tag: GcpTag,

src/enums/services.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ export default {
77
// ml: 'ml',
88
// mlEngine: 'ml-engine',
99
// notebooks: 'notebooks',
10-
// apiGateway: 'api-gateway',
10+
apiGatewayGateway: 'apiGatewayGateways',
11+
apiGatewayApi: 'apiGatewayApis',
12+
apiGatewayApiConfig: 'apiGatewayApiConfigs',
1113
// apigee: 'apigee',
1214
// endpoints: 'endpoints',
1315
// recommender: 'recommender',
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { ServiceConnection } from '@cloudgraph/sdk'
2+
import { RawGcpApiGatewayApi } from './data'
3+
4+
import services from '../../enums/services'
5+
import { RawGcpApiGatewayGateway } from '../apiGatewayGateway/data'
6+
7+
export default ({
8+
service,
9+
data,
10+
}: {
11+
service: RawGcpApiGatewayApi
12+
data: { name: string; data: { [property: string]: any[] } }[]
13+
region: string
14+
}): {
15+
[property: string]: ServiceConnection[]
16+
} => {
17+
const { id } = service
18+
const connections: ServiceConnection[] = []
19+
20+
/**
21+
* Find Api Gateway Gateways
22+
*/
23+
const gateways: {
24+
name: string
25+
data: { [property: string]: any[] }
26+
} = data.find(({ name }) => name === services.apiGatewayGateway)
27+
28+
if (gateways?.data) {
29+
for (const region of Object.keys(gateways.data)) {
30+
const filteredGateways = gateways.data[region].filter(
31+
({ apiConfig }: RawGcpApiGatewayGateway) => {
32+
const idSessions = apiConfig.split('/')
33+
idSessions[1] = service.projectId
34+
const apiIdWithNumber = idSessions.join('/')
35+
return apiIdWithNumber.startsWith(`${id}/`)
36+
}
37+
)
38+
39+
if (filteredGateways) {
40+
for (const filteredGateway of filteredGateways) {
41+
connections.push({
42+
id: filteredGateway.id,
43+
resourceType: services.apiGatewayGateway,
44+
relation: 'child',
45+
field: 'apiGatewayGateways',
46+
})
47+
}
48+
}
49+
}
50+
}
51+
52+
const result = {
53+
[service.id]: connections,
54+
}
55+
return result
56+
}

src/services/apiGatewayApi/data.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import groupBy from 'lodash/groupBy'
2+
import { ApiGatewayServiceClient } from '@google-cloud/api-gateway'
3+
import CloudGraph from '@cloudgraph/sdk'
4+
import { google } from '@google-cloud/api-gateway/build/protos/protos'
5+
import gcpLoggerText from '../../properties/logger'
6+
import { GcpServiceInput, LabelMap } from '../../types'
7+
import { generateGcpErrorLog, initTestEndpoint } from '../../utils'
8+
import { GLOBAL_REGION } from '../../config/constants'
9+
10+
const lt = { ...gcpLoggerText }
11+
const { logger } = CloudGraph
12+
const serviceName = 'API Gateway Api'
13+
const apiEndpoint = initTestEndpoint(serviceName)
14+
15+
export interface RawGcpApiGatewayApi extends
16+
Omit<google.cloud.apigateway.v1.IApi, 'labels'> {
17+
id: string,
18+
region: string,
19+
projectId: string,
20+
Labels: LabelMap,
21+
}
22+
23+
export const listApiGatewayApiData = async (
24+
apiGatewayClient: ApiGatewayServiceClient,
25+
projectId: string,
26+
apiData: RawGcpApiGatewayApi[],
27+
): Promise<void> => {
28+
try {
29+
const apiIter = apiGatewayClient.listApisAsync({
30+
parent: `projects/${projectId}/locations/${GLOBAL_REGION}`,
31+
})
32+
for await (const {name, labels, ...api} of apiIter) {
33+
apiData.push({
34+
id: name,
35+
projectId,
36+
region: GLOBAL_REGION,
37+
Labels: labels,
38+
...api,
39+
})
40+
}
41+
} catch (error) {
42+
generateGcpErrorLog(serviceName, 'ApiGateway:listApisAsync', error)
43+
}
44+
}
45+
46+
export default async ({
47+
config,
48+
}: GcpServiceInput): Promise<{
49+
[region: string]: RawGcpApiGatewayApi[]
50+
}> => {
51+
const { projectId } = config
52+
53+
const apiData: RawGcpApiGatewayApi[] = []
54+
const apiGatewayClient = new ApiGatewayServiceClient({ ...config, apiEndpoint })
55+
56+
await listApiGatewayApiData(apiGatewayClient, projectId, apiData)
57+
58+
logger.debug(lt.foundResources(serviceName, apiData.length))
59+
60+
return groupBy(apiData, 'region')
61+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { google } from '@google-cloud/api-gateway/build/protos/protos'
2+
import { RawGcpApiGatewayApi } from './data'
3+
import { enumKeyToString, formatLabelsFromMap } from '../../utils/format'
4+
import { GcpApiGatewayApi } from '../../types/generated'
5+
import { toISOString } from '../../utils/dateutils'
6+
7+
export default ({
8+
service,
9+
account,
10+
region,
11+
}: {
12+
service: RawGcpApiGatewayApi
13+
account: string
14+
region: string
15+
}): GcpApiGatewayApi => {
16+
const {
17+
id,
18+
Labels,
19+
createTime,
20+
updateTime,
21+
displayName,
22+
managedService,
23+
state,
24+
} = service
25+
26+
return {
27+
id,
28+
name: displayName,
29+
projectId: account,
30+
region,
31+
labels: formatLabelsFromMap(Labels),
32+
createTime: toISOString(createTime?.seconds?.toString()) || '',
33+
updateTime: toISOString(updateTime?.seconds?.toString()) || '',
34+
managedService,
35+
state: enumKeyToString(google.cloud.apigateway.v1.Api.State, state),
36+
}
37+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Service } from '@cloudgraph/sdk'
2+
import BaseService from '../base'
3+
import format from './format'
4+
import getData from './data'
5+
import getConnections from './connections'
6+
import mutation from './mutation'
7+
8+
export default class GcpApiGatewayApi extends BaseService implements Service {
9+
format = format.bind(this)
10+
11+
getData = getData.bind(this)
12+
13+
getConnections = getConnections.bind(this)
14+
15+
mutation = mutation;
16+
}

0 commit comments

Comments
 (0)