Skip to content

Commit d1e9f42

Browse files
feature(cdn): add cdn backend service
1 parent c9fd809 commit d1e9f42

11 files changed

Lines changed: 535 additions & 0 deletions

File tree

src/enums/schemasMap.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default {
1616
[services.kmsCryptoKeys]: 'gcpKmsCryptoKey',
1717
[services.cdnBackendBucket]: 'gcpCdnBackendBucket',
1818
[services.cloudRouter]: 'gcpCloudRouter',
19+
[services.cdnBackendService]: 'gcpCdnBackendService',
1920
[services.dnsManagedZone]: 'gcpDnsManagedZone',
2021
[services.dnsPolicy]: 'gcpDnsPolicy',
2122
[services.vpcConnector]: 'gcpVpcConnector',

src/enums/serviceMap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import GcpKmsKeyRing from '../services/kms'
1010
import GcpKmsCryptoKey from '../services/kmsCryptoKey'
1111
import GcpCloudRouter from '../services/cloudRouter'
1212
import GcpCdnBackendBucket from '../services/cdnBackendBucket'
13+
import GcpCdnBackendService from '../services/cdnBackendService'
1314
import GcpDnsManagedZone from '../services/dnsManagedZone'
1415
import GcpVpc from '../services/vpc'
1516
import GcpIam from '../services/iam'
@@ -55,6 +56,7 @@ export default {
5556
[services.kmsCryptoKeys]: GcpKmsCryptoKey,
5657
[services.cloudRouter]: GcpCloudRouter,
5758
[services.cdnBackendBucket]: GcpCdnBackendBucket,
59+
[services.cdnBackendService]: GcpCdnBackendService,
5860
[services.dnsManagedZone]: GcpDnsManagedZone,
5961
[services.dnsPolicy]: GcpDnsPolicy,
6062
[services.vpcConnector]: GcpVpc,

src/enums/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default {
2323
// compute: 'compute',
2424
// container: 'container',
2525
cdnBackendBucket: 'cdnBackendBucket',
26+
cdnBackendService: 'cdnBackendService',
2627
cloudFunction: 'cloudFunction',
2728
computeProject: 'computeProject',
2829
// run: 'run',
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import groupBy from 'lodash/groupBy'
2+
import CloudGraph from '@cloudgraph/sdk'
3+
import { BackendServicesClient } from '@google-cloud/compute'
4+
import { google } from '@google-cloud/compute/build/protos/protos'
5+
import gcpLoggerText from '../../properties/logger'
6+
import { GcpServiceInput } 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 = 'CDN Backend Service'
13+
const apiEndpoint = initTestEndpoint(serviceName)
14+
15+
export interface RawGcpCdnBackendService extends Omit<google.cloud.compute.v1.IBackendService, 'id' | 'network'> {
16+
id: string
17+
projectId: string
18+
region: string
19+
network: string[]
20+
}
21+
22+
export default async ({
23+
config,
24+
}: GcpServiceInput): Promise<{
25+
[region: string]: RawGcpCdnBackendService[]
26+
}> => {
27+
const backendServices: RawGcpCdnBackendService[] = []
28+
const { projectId } = config
29+
30+
const computeClient = new BackendServicesClient({ ...config, apiEndpoint })
31+
32+
try {
33+
const backendServiceIter = computeClient.listAsync({project: projectId})
34+
for await (const backendService of backendServiceIter) {
35+
backendServices.push({
36+
...backendService,
37+
id: backendService.id.toString(),
38+
projectId,
39+
region: GLOBAL_REGION,
40+
network: backendService.network? [backendService.network] : [],
41+
})
42+
}
43+
} catch (error) {
44+
generateGcpErrorLog(serviceName, 'cdnBackendService:listAsync', error)
45+
}
46+
47+
logger.debug(lt.foundResources(serviceName, backendServices.length))
48+
49+
return groupBy(backendServices, 'region')
50+
}
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import { google } from '@google-cloud/compute/build/protos/protos'
2+
3+
import cuid from 'cuid'
4+
import { RawGcpCdnBackendService } from './data'
5+
import { enumKeyToString } from '../../utils/format'
6+
import {
7+
GcpCdnBackendService,
8+
GcpCdnBackendServiceBackend,
9+
GcpCdnBackendServiceCdnPolicy,
10+
GcpCdnBackendServiceCdnPolicyNegativeCachingPolicy,
11+
GcpCdnBackendServiceOutlierDetection,
12+
} from '../../types/generated'
13+
import { toISOString } from '../../utils/dateutils'
14+
15+
const formatBackend = ({
16+
balancingMode,
17+
capacityScaler,
18+
description,
19+
failover,
20+
group,
21+
maxConnections,
22+
maxConnectionsPerEndpoint,
23+
maxConnectionsPerInstance,
24+
maxRate,
25+
maxRatePerEndpoint,
26+
maxRatePerInstance,
27+
maxUtilization,
28+
}: google.cloud.compute.v1.IBackend): GcpCdnBackendServiceBackend => {
29+
return {
30+
id: cuid(),
31+
balancingMode: enumKeyToString(google.cloud.compute.v1.Backend.BalancingMode, balancingMode),
32+
capacityScaler,
33+
description,
34+
failover,
35+
group,
36+
maxConnections,
37+
maxConnectionsPerEndpoint,
38+
maxConnectionsPerInstance,
39+
maxRate,
40+
maxRatePerEndpoint,
41+
maxRatePerInstance,
42+
maxUtilization,
43+
}
44+
}
45+
46+
const formatCdnPolicyNegativeCachingPolicy = ({
47+
code,
48+
ttl,
49+
}: google.cloud.compute.v1.IBackendServiceCdnPolicyNegativeCachingPolicy): GcpCdnBackendServiceCdnPolicyNegativeCachingPolicy => {
50+
return {
51+
id: cuid(),
52+
code,
53+
ttl,
54+
}
55+
}
56+
57+
const formatCdnPolicy = ({
58+
bypassCacheOnRequestHeaders = [],
59+
cacheKeyPolicy,
60+
cacheMode,
61+
clientTtl,
62+
defaultTtl,
63+
maxTtl,
64+
negativeCaching,
65+
negativeCachingPolicy = [],
66+
requestCoalescing,
67+
serveWhileStale,
68+
signedUrlCacheMaxAgeSec,
69+
signedUrlKeyNames,
70+
}: google.cloud.compute.v1.IBackendServiceCdnPolicy): GcpCdnBackendServiceCdnPolicy => {
71+
return {
72+
bypassCacheOnRequestHeaderNames: bypassCacheOnRequestHeaders?.map(
73+
header => header?.headerName || ''
74+
),
75+
cacheKeyPolicyIncludeHost: cacheKeyPolicy?.includeHost || false,
76+
cacheKeyPolicyIncludeProtocol: cacheKeyPolicy?.includeProtocol || false,
77+
cacheKeyPolicyIncludeQueryString: cacheKeyPolicy?.includeQueryString || false,
78+
cacheKeyPolicyQueryStringBlacklist: cacheKeyPolicy?.queryStringBlacklist || [],
79+
cacheKeyPolicyQueryStringWhitelist: cacheKeyPolicy?.queryStringWhitelist || [],
80+
cacheMode: enumKeyToString(google.cloud.compute.v1.BackendServiceCdnPolicy.CacheMode, cacheMode),
81+
clientTtl,
82+
defaultTtl,
83+
maxTtl,
84+
negativeCaching,
85+
negativeCachingPolicy: negativeCachingPolicy?.map(policy => formatCdnPolicyNegativeCachingPolicy(policy)),
86+
requestCoalescing,
87+
serveWhileStale,
88+
signedUrlCacheMaxAgeSec: signedUrlCacheMaxAgeSec?.toString() || '',
89+
signedUrlKeyNames,
90+
}
91+
}
92+
93+
const formatOutlierDetection = ({
94+
baseEjectionTime,
95+
consecutiveErrors,
96+
consecutiveGatewayFailure,
97+
enforcingConsecutiveErrors,
98+
enforcingConsecutiveGatewayFailure,
99+
enforcingSuccessRate,
100+
interval,
101+
maxEjectionPercent,
102+
successRateMinimumHosts,
103+
successRateRequestVolume,
104+
successRateStdevFactor,
105+
}: google.cloud.compute.v1.IOutlierDetection): GcpCdnBackendServiceOutlierDetection => {
106+
return {
107+
baseEjectionTime: toISOString(baseEjectionTime?.seconds?.toString()) || '',
108+
consecutiveErrors,
109+
consecutiveGatewayFailure,
110+
enforcingConsecutiveErrors,
111+
enforcingConsecutiveGatewayFailure,
112+
enforcingSuccessRate,
113+
interval: toISOString(interval?.seconds?.toString()) || '',
114+
maxEjectionPercent,
115+
successRateMinimumHosts,
116+
successRateRequestVolume,
117+
successRateStdevFactor,
118+
}
119+
}
120+
121+
export default ({
122+
service,
123+
account,
124+
region,
125+
}: {
126+
service: RawGcpCdnBackendService
127+
account: string
128+
region: string
129+
}): GcpCdnBackendService => {
130+
const {
131+
affinityCookieTtlSec,
132+
backends = [],
133+
cdnPolicy = {},
134+
circuitBreakers,
135+
connectionDraining,
136+
consistentHash,
137+
creationTimestamp,
138+
customRequestHeaders,
139+
customResponseHeaders,
140+
description,
141+
enableCDN,
142+
failoverPolicy,
143+
fingerprint,
144+
healthChecks,
145+
iap,
146+
id,
147+
kind,
148+
loadBalancingScheme,
149+
localityLbPolicy,
150+
logConfig,
151+
maxStreamDuration,
152+
name,
153+
outlierDetection = {},
154+
port,
155+
portName,
156+
protocol,
157+
securityPolicy,
158+
securitySettings,
159+
selfLink,
160+
sessionAffinity,
161+
timeoutSec,
162+
} = service
163+
164+
return {
165+
id,
166+
projectId: account,
167+
region,
168+
name,
169+
affinityCookieTtlSec,
170+
backends: backends?.map(backend => formatBackend(backend)),
171+
cdnPolicy: formatCdnPolicy(cdnPolicy),
172+
circuitBreakersMaxConnections: circuitBreakers?.maxConnections || 0,
173+
circuitBreakersMaxPendingRequests: circuitBreakers?.maxPendingRequests || 0,
174+
circuitBreakersMaxRequests: circuitBreakers?.maxRequests || 0,
175+
circuitBreakersMaxRequestsPerConnection: circuitBreakers?.maxRequestsPerConnection || 0,
176+
circuitBreakersMaxRetries: circuitBreakers?.maxRetries || 0,
177+
connectionDrainingTimeoutSec: connectionDraining?.drainingTimeoutSec || 0,
178+
consistentHashLoadBalancerSettingHttpCookieName: consistentHash?.httpCookie?.name || '',
179+
consistentHashLoadBalancerSettingHttpCookiePath: consistentHash?.httpCookie?.path || '',
180+
consistentHashLoadBalancerSettingHttpCookie: toISOString(consistentHash?.httpCookie?.ttl.seconds?.toString()) || '',
181+
consistentHashLoadBalancerSettingHttpHeaderName: consistentHash?.httpHeaderName || '',
182+
consistentHashLoadBalancerSettingMinimumRingSize: consistentHash?.minimumRingSize?.toString() || '',
183+
creationTimestamp,
184+
customRequestHeaders,
185+
customResponseHeaders,
186+
description,
187+
enableCDN,
188+
failoverPolicyDisableConnectionDrainOnFailover: failoverPolicy?.disableConnectionDrainOnFailover || false,
189+
failoverPolicyDropTrafficIfUnhealthy: failoverPolicy?.dropTrafficIfUnhealthy || false,
190+
failoverPolicyFailoverRatio: failoverPolicy?.failoverRatio || 0,
191+
fingerprint,
192+
healthChecks,
193+
iapEnabled: iap?.enabled || false,
194+
iapOauth2ClientId: iap?.oauth2ClientId || '',
195+
// remove the secrets
196+
// oauth2ClientSecret
197+
// oauth2ClientSecretSha256
198+
kind,
199+
loadBalancingScheme: enumKeyToString(google.cloud.compute.v1.BackendService.LoadBalancingScheme, loadBalancingScheme),
200+
localityLbPolicy: enumKeyToString(google.cloud.compute.v1.BackendService.LocalityLbPolicy, localityLbPolicy),
201+
logConfigEnable: logConfig?.enable || false,
202+
logConfigSampleRate: logConfig?.sampleRate || 0,
203+
maxStreamDuration: toISOString(maxStreamDuration?.seconds?.toString()),
204+
outlierDetection: formatOutlierDetection(outlierDetection),
205+
port,
206+
portName,
207+
protocol: enumKeyToString(google.cloud.compute.v1.BackendService.Protocol, protocol),
208+
securityPolicy,
209+
securitySettingClientTlsPolicy: securitySettings?.clientTlsPolicy || '',
210+
securitySettingSubjectAltNames: securitySettings?.subjectAltNames || [],
211+
selfLink,
212+
sessionAffinity: enumKeyToString(google.cloud.compute.v1.BackendService.SessionAffinity, sessionAffinity),
213+
timeoutSec,
214+
}
215+
}
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 GcpCdnBackendService 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: [AddgcpCdnBackendServiceInput!]!) {
2+
addgcpCdnBackendService(input: $input, upsert: true) {
3+
numUids
4+
}
5+
}`;

0 commit comments

Comments
 (0)