Skip to content

Commit 008ff39

Browse files
committed
Merge branch 'feature/CG-530' into 'main'
CG-530: feat(label/tag): add labels/tags as services Closes CG-530 See merge request auto-cloud/cloudgraph/provider/cloudgraph-provider-gcp!47
2 parents 0ed384d + 853d37b commit 008ff39

19 files changed

Lines changed: 294 additions & 107 deletions

File tree

src/enums/serviceMap.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import GcpCdnUrlMap from '../services/cdnUrlMap'
1515
import GcpDnsManagedZone from '../services/dnsManagedZone'
1616
import GcpVpc from '../services/vpc'
1717
import GcpIam from '../services/iam'
18-
import GcpTag from '../services/tag'
1918
import GcpLogBucket from '../services/logBucket'
2019
import GcpLogSink from '../services/logSink'
2120
import GcpLogView from '../services/logView'
@@ -44,6 +43,8 @@ import GcpDataprocAutoscalingPolicy from '../services/dataprocAutoscalingPolicy'
4443
import GcpDataprocJob from '../services/dataprocJob'
4544
import GcpDataprocWorkflowTemplate from '../services/dataprocWorkflowTemplate'
4645
import GcpFirestoreDatabase from '../services/firestore'
46+
import GcpLabel from '../services/label'
47+
import GcpTag from '../services/tag'
4748

4849
/**
4950
* serviceMap is an object that contains all currently supported services
@@ -94,5 +95,6 @@ export default {
9495
[services.dataprocJob]: GcpDataprocJob,
9596
[services.dataprocWorkflowTemplate]: GcpDataprocWorkflowTemplate,
9697
[services.firestoreDatabase]: GcpFirestoreDatabase,
98+
label: GcpLabel,
9799
tag: GcpTag,
98100
}

src/enums/services.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default {
6767
// recaptcha: 'recaptcha',
6868
// resourceManager: 'resource-manager',
6969
// resourceSettings: 'resource-settings',
70-
secretManager: 'secretManager',
70+
secretManager: 'secrets',
7171
// iot: 'iot',
7272
// cloudShell: 'cloud-shell',
7373
// debug: 'debug',

src/services/alertPolicy/format.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default ({
3535
region,
3636
displayName,
3737
documentation,
38-
userLabels: formatLabelsFromMap(userLabels),
38+
labels: formatLabelsFromMap(userLabels),
3939
conditions: conditions?.map(condition => ({
4040
id: cuid(),
4141
name: condition?.name,

src/services/alertPolicy/schema.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
type gcpAlertPolicy implements gcpBaseResource @key(fields: "id") {
22
displayName: String @search(by: [hash, regexp])
33
documentation: gcpAlertPolicyDocumentation
4-
userLabels: [gcpRawLabel]
4+
labels: [gcpRawLabel]
55
conditions: [gcpAlertPolicyCondition]
66
combiner: String @search(by: [hash, regexp])
77
enabled: gcpBoolValue

src/services/index.ts

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ export default class Provider extends CloudGraph.Client {
279279
}
280280
const resourceNames: string[] = sortResourcesDependencies(relations, [
281281
...new Set<string>(configuredResources.split(',')),
282-
])
282+
]).concat(['label', 'tag'])
283+
283284
const { projectId } = account
284285
const config = { ...account }
285286

@@ -351,8 +352,6 @@ export default class Provider extends CloudGraph.Client {
351352
// data so we can pass along accountId
352353
// TODO: find a better way to handle this
353354
let mergedRawData: rawDataInterface[] = []
354-
const tagRegion = GLOBAL_REGION
355-
const tags = { name: 'tag', data: { [tagRegion]: [] } }
356355
const crawledAccounts = []
357356
for (const account of configuredAccounts) {
358357
const { projectId } = account
@@ -370,43 +369,6 @@ export default class Provider extends CloudGraph.Client {
370369
}
371370
}
372371

373-
// Handle global tag entities
374-
try {
375-
for (const { data: entityData } of rawData) {
376-
for (const region of Object.keys(entityData)) {
377-
const dataAtRegion = entityData[region]
378-
dataAtRegion.forEach(singleEntity => {
379-
if (!isEmpty(singleEntity.Tags)) {
380-
for (const [key, value] of Object.entries(singleEntity.Tags)) {
381-
if (
382-
!tags.data[tagRegion].find(
383-
({ id }) => id === `${key}:${value}`
384-
)
385-
) {
386-
tags.data[tagRegion].push({
387-
id: `${key}:${value}`,
388-
key,
389-
value,
390-
})
391-
}
392-
}
393-
}
394-
})
395-
}
396-
}
397-
const existingTagsIdx = rawData.findIndex(({ name }) => {
398-
return name === 'tag'
399-
})
400-
if (existingTagsIdx > -1) {
401-
rawData[existingTagsIdx] = tags
402-
} else {
403-
rawData.push(tags)
404-
}
405-
} catch (error: any) {
406-
this.logger.error('There was an error aggregating tags')
407-
this.logger.debug(error)
408-
}
409-
410372
/**
411373
* Loop through the sdk data to format entities and build connections
412374
* 1. Format data with provider service format function

src/services/label/connections.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ServiceConnection } from '@cloudgraph/sdk'
2+
import { rawDataInterface } from '../../types'
3+
import { GLOBAL_REGION } from '../../config/constants'
4+
import services from '../../enums/services'
5+
6+
export default ({
7+
service,
8+
data,
9+
region,
10+
}: {
11+
service: any
12+
data: Array<{ name: string; data: { [property: string]: any[] } }>
13+
region: string
14+
}): {
15+
[property: string]: ServiceConnection[]
16+
} => {
17+
const { id } = service
18+
const connections: ServiceConnection[] = []
19+
const connectTo = Object.values(services)
20+
21+
for (const serviceName of connectTo) {
22+
const instances: {
23+
name: string
24+
data: { [property: string]: any[] }
25+
} = data.find(({ name }) => name === serviceName)
26+
27+
const regions = [region, GLOBAL_REGION]
28+
for (const region of regions) {
29+
if (instances?.data?.[region]) {
30+
const filtered = instances.data[region].filter(
31+
({ labels }: rawDataInterface) => !!labels
32+
)
33+
34+
for (const instance of filtered) {
35+
if (instance) {
36+
connections.push({
37+
id: instance.id,
38+
resourceType: serviceName,
39+
relation: 'child',
40+
field: serviceName,
41+
})
42+
}
43+
}
44+
}
45+
}
46+
}
47+
48+
const labelResult = {
49+
[id]: connections,
50+
}
51+
return labelResult
52+
}

src/services/label/data.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import groupBy from 'lodash/groupBy'
2+
import isEmpty from 'lodash/isEmpty'
3+
import CloudGraph from '@cloudgraph/sdk'
4+
import gcpLoggerText from '../../properties/logger'
5+
import { generateGcpErrorLog } from '../../utils'
6+
import { GcpServiceInput } from '../../types'
7+
import { GcpLabel } from '../../types/generated'
8+
9+
const lt = { ...gcpLoggerText }
10+
const { logger } = CloudGraph
11+
const serviceName = 'Label'
12+
13+
export interface RawGcpLabel extends GcpLabel {
14+
id: string
15+
projectId: string
16+
region: string
17+
}
18+
19+
export default async ({
20+
config,
21+
rawData,
22+
}: GcpServiceInput): Promise<{
23+
[region: string]: RawGcpLabel[]
24+
}> =>
25+
new Promise(async resolve => {
26+
const labelList: RawGcpLabel[] = []
27+
const { projectId } = config
28+
29+
try {
30+
for (const { data: entityData } of rawData) {
31+
for (const region of Object.keys(entityData)) {
32+
const dataAtRegion = entityData[region]
33+
dataAtRegion.forEach(singleEntity => {
34+
if (!isEmpty(singleEntity.labels)) {
35+
for (const [key, value] of Object.entries(singleEntity.labels)) {
36+
if (
37+
!labelList.find(
38+
({ id }) => id === `${singleEntity.id}:${key}:${value}`
39+
)
40+
) {
41+
labelList.push({
42+
id: `${singleEntity.id}:${key}:${value}`,
43+
projectId,
44+
key,
45+
value: String(value),
46+
region,
47+
})
48+
}
49+
}
50+
}
51+
})
52+
}
53+
}
54+
} catch (error: any) {
55+
generateGcpErrorLog(serviceName, '', error)
56+
}
57+
58+
logger.debug(lt.foundResources(serviceName, labelList.length))
59+
resolve(groupBy(labelList, 'region'))
60+
})

src/services/label/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Service } from '@cloudgraph/sdk';
2+
import BaseService from '../base';
3+
import getConnections from './connections';
4+
import getData from './data'
5+
import mutation from './mutation';
6+
7+
export default class GcpLabel extends BaseService implements Service {
8+
format = ({service}: {service: any}): any => service
9+
10+
getConnections = getConnections.bind(this)
11+
12+
getData = getData.bind(this)
13+
14+
mutation = mutation;
15+
}

src/services/label/mutation.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default `mutation($input: [AddgcpLabelInput!]!) {
2+
addgcpLabel(input: $input, upsert: true) {
3+
numUids
4+
}
5+
}`;

src/services/label/schema.graphql

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
type gcpLabel implements gcpBaseResource @key(fields: "id") {
2+
id: String! @id @search(by: [hash])
3+
key: String! @search(by: [hash, regexp])
4+
value: String! @search(by: [hash, regexp])
5+
alertPolicy: [gcpAlertPolicy]
6+
cloudFunction: [gcpCloudFunction]
7+
dnsManagedZone: [gcpDnsManagedZone]
8+
kmsCryptoKey: [gcpKmsCryptoKey]
9+
project: [gcpProject]
10+
secrets: [gcpSecret]
11+
storageBucket: [gcpStorageBucket]
12+
vmInstance: [gcpVmInstance]
13+
}
14+
15+
type gcpRawLabel
16+
@generate(
17+
query: { get: false, query: false, aggregate: false }
18+
mutation: { add: false, delete: false }
19+
subscription: false
20+
) {
21+
id: String! @id
22+
key: String
23+
value: String
24+
}

0 commit comments

Comments
 (0)