@intentius/chant-lexicon-gcp 0.44.14 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/src/codegen/docs.ts +0 -726
- package/src/lint/post-synth/post-synth.test.ts +2 -3
- package/src/lint/post-synth/wgc101.test.ts +2 -3
- package/src/lint/post-synth/wgc102.test.ts +2 -3
- package/src/lint/post-synth/wgc103.test.ts +2 -3
- package/src/lint/post-synth/wgc104.test.ts +2 -3
- package/src/lint/post-synth/wgc105.test.ts +2 -3
- package/src/lint/post-synth/wgc106.test.ts +2 -3
- package/src/lint/post-synth/wgc107.test.ts +2 -3
- package/src/lint/post-synth/wgc108.test.ts +2 -3
- package/src/lint/post-synth/wgc109.test.ts +2 -3
- package/src/lint/post-synth/wgc110.test.ts +2 -3
- package/src/lint/post-synth/wgc111.test.ts +2 -3
- package/src/lint/post-synth/wgc112.test.ts +2 -3
- package/src/lint/post-synth/wgc113.test.ts +2 -3
- package/src/lint/post-synth/wgc201.test.ts +2 -3
- package/src/lint/post-synth/wgc202.test.ts +2 -3
- package/src/lint/post-synth/wgc203.test.ts +2 -3
- package/src/lint/post-synth/wgc204.test.ts +2 -3
- package/src/lint/post-synth/wgc301.test.ts +2 -3
- package/src/lint/post-synth/wgc302.test.ts +2 -3
- package/src/lint/post-synth/wgc303.test.ts +2 -3
- package/src/lint/post-synth/wgc401.test.ts +2 -3
- package/src/lint/post-synth/wgc402.test.ts +2 -3
- package/src/lint/post-synth/wgc403.test.ts +2 -3
- package/src/serializer.test.ts +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4FH;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4FH;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB9E"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "17362bbe86bdedd7a3825faca8213f558c72714c6f6f16ce27dfd207c329b1ea",
|
|
5
5
|
"meta.json": "475f10909854d059a2e2d4fb541c058803422e38b9c64bd4d6858c0623eedb8c",
|
|
6
6
|
"types/index.d.ts": "5433b54c04b57d6fda8f3d81ef92ed0aca87f7e8e5dd3ea92d8de6e62a3ccfab",
|
|
7
7
|
"rules/hardcoded-project.ts": "228631d3159e1ffcce2359c66073d4ae59bb0285f378e46e446f416aec50481c",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"skills/chant-gcp-patterns.md": "a7ef31c1eb2f7244d3f73952c300472ef94c1eb09bd7a1003281b89299b6b704",
|
|
41
41
|
"skills/chant-gcp-gke.md": "be277019da9a722c851e47cd2dfb9c9536668948c3535fb20db7697e934c4e2b"
|
|
42
42
|
},
|
|
43
|
-
"composite": "
|
|
43
|
+
"composite": "5d1b64bafea0ac5f419bf20633a22c2d6a49d498ad6e63aba5d89523492dcc79"
|
|
44
44
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-gcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"description": "Google Cloud lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"typescript": "^5.9.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@intentius/chant": "^0.
|
|
79
|
+
"@intentius/chant": "^0.45.0",
|
|
80
80
|
"typescript": "^5.9.3"
|
|
81
81
|
}
|
|
82
82
|
}
|
package/src/codegen/docs.ts
CHANGED
|
@@ -111,732 +111,6 @@ export async function generateDocs(opts?: { verbose?: boolean }): Promise<void>
|
|
|
111
111
|
serviceFromType,
|
|
112
112
|
srcDir: join(pkgDir, "src"),
|
|
113
113
|
basePath: "/chant/lexicons/gcp/",
|
|
114
|
-
extraPages: [
|
|
115
|
-
{
|
|
116
|
-
slug: "getting-started",
|
|
117
|
-
title: "Getting Started",
|
|
118
|
-
description: "Install chant and deploy your first GCP resource in 5 minutes",
|
|
119
|
-
content: `## What is chant?
|
|
120
|
-
|
|
121
|
-
Chant is a TypeScript-to-YAML compiler. You write typed TypeScript declarations, and chant outputs Config Connector YAML manifests that can be applied to a GKE cluster with Config Connector installed.
|
|
122
|
-
|
|
123
|
-
## Prerequisites
|
|
124
|
-
|
|
125
|
-
1. A GKE cluster with [Config Connector](https://cloud.google.com/config-connector/docs/overview) installed
|
|
126
|
-
2. A \`ConfigConnectorContext\` resource configured per namespace
|
|
127
|
-
3. A GCP Service Account bound to the Config Connector controller
|
|
128
|
-
|
|
129
|
-
## Install
|
|
130
|
-
|
|
131
|
-
\`\`\`bash
|
|
132
|
-
npm install --save-dev @intentius/chant @intentius/chant-lexicon-gcp
|
|
133
|
-
\`\`\`
|
|
134
|
-
|
|
135
|
-
## Your first resource
|
|
136
|
-
|
|
137
|
-
The fastest path is the **GcsBucket** composite — one function call that produces a properly configured Storage bucket:
|
|
138
|
-
|
|
139
|
-
\`\`\`typescript
|
|
140
|
-
// src/infra.gcp.ts
|
|
141
|
-
import { GcsBucket } from "@intentius/chant-lexicon-gcp";
|
|
142
|
-
import { defaultAnnotations, GCP } from "@intentius/chant-lexicon-gcp";
|
|
143
|
-
|
|
144
|
-
export const annotations = defaultAnnotations({
|
|
145
|
-
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
const { bucket } = GcsBucket({
|
|
149
|
-
name: "my-data-bucket",
|
|
150
|
-
location: "US",
|
|
151
|
-
versioning: true,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
export { bucket };
|
|
155
|
-
\`\`\`
|
|
156
|
-
|
|
157
|
-
## Build and deploy
|
|
158
|
-
|
|
159
|
-
\`\`\`bash
|
|
160
|
-
# Generate Config Connector YAML
|
|
161
|
-
chant build --output dist/manifests.yaml
|
|
162
|
-
|
|
163
|
-
# Validate against the cluster API (no changes applied)
|
|
164
|
-
kubectl apply -f dist/manifests.yaml --dry-run=server
|
|
165
|
-
|
|
166
|
-
# Apply
|
|
167
|
-
kubectl apply -f dist/manifests.yaml
|
|
168
|
-
\`\`\`
|
|
169
|
-
|
|
170
|
-
## Using resource constructors
|
|
171
|
-
|
|
172
|
-
\`\`\`typescript
|
|
173
|
-
import { StorageBucket, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
|
|
174
|
-
|
|
175
|
-
export const bucket = new StorageBucket({
|
|
176
|
-
location: "US",
|
|
177
|
-
storageClass: "STANDARD",
|
|
178
|
-
uniformBucketLevelAccess: true,
|
|
179
|
-
versioning: { enabled: true },
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
export const reader = new IAMPolicyMember({
|
|
183
|
-
member: "serviceAccount:app@my-project.iam.gserviceaccount.com",
|
|
184
|
-
role: "roles/storage.objectViewer",
|
|
185
|
-
resourceRef: {
|
|
186
|
-
apiVersion: "storage.cnrm.cloud.google.com/v1beta1",
|
|
187
|
-
kind: "StorageBucket",
|
|
188
|
-
name: bucket,
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
\`\`\`
|
|
192
|
-
|
|
193
|
-
## Next steps
|
|
194
|
-
|
|
195
|
-
- [Config Connector Concepts](/chant/lexicons/gcp/config-connector-concepts/) — resource structure, references, project binding
|
|
196
|
-
- [Examples](/chant/lexicons/gcp/examples/) — StorageBucket, ComputeInstance, CloudSQL, IAM
|
|
197
|
-
- [Lint Rules](/chant/lexicons/gcp/lint-rules/) — built-in checks for security and best practices`,
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
slug: "config-connector-concepts",
|
|
201
|
-
title: "Config Connector Concepts",
|
|
202
|
-
description: "Resource structure, resourceRef, project binding, reconciliation lifecycle",
|
|
203
|
-
content: `import Diagram from '../../components/Diagram.astro';
|
|
204
|
-
|
|
205
|
-
Every exported resource declaration becomes a Config Connector manifest document in the generated YAML.
|
|
206
|
-
|
|
207
|
-
## Resource structure
|
|
208
|
-
|
|
209
|
-
Every Config Connector resource has four standard fields:
|
|
210
|
-
|
|
211
|
-
| Field | Source | Example |
|
|
212
|
-
|-------|--------|---------|
|
|
213
|
-
| \`apiVersion\` | Resolved from resource type | \`storage.cnrm.cloud.google.com/v1beta1\` |
|
|
214
|
-
| \`kind\` | Resolved from resource type | \`StorageBucket\` |
|
|
215
|
-
| \`metadata\` | From \`metadata\` property | \`{ name: "my-bucket", labels: {...} }\` |
|
|
216
|
-
| \`spec\` | From remaining props | Resource-specific configuration |
|
|
217
|
-
|
|
218
|
-
## Resource references
|
|
219
|
-
|
|
220
|
-
Config Connector resources reference each other using \`resourceRef\`:
|
|
221
|
-
|
|
222
|
-
\`\`\`yaml
|
|
223
|
-
# By name (same namespace)
|
|
224
|
-
resourceRef:
|
|
225
|
-
name: my-network
|
|
226
|
-
|
|
227
|
-
# By external reference (cross-project)
|
|
228
|
-
resourceRef:
|
|
229
|
-
external: projects/my-project/global/networks/my-network
|
|
230
|
-
\`\`\`
|
|
231
|
-
|
|
232
|
-
In chant, resource references resolve automatically:
|
|
233
|
-
|
|
234
|
-
\`\`\`typescript
|
|
235
|
-
export const network = new ComputeNetwork({ autoCreateSubnetworks: false });
|
|
236
|
-
|
|
237
|
-
export const subnet = new ComputeSubnetwork({
|
|
238
|
-
networkRef: { name: network }, // Resolves to metadata.name of network
|
|
239
|
-
ipCidrRange: "10.0.0.0/24",
|
|
240
|
-
region: "us-central1",
|
|
241
|
-
});
|
|
242
|
-
\`\`\`
|
|
243
|
-
|
|
244
|
-
## Project binding
|
|
245
|
-
|
|
246
|
-
Bind resources to a GCP project via annotations:
|
|
247
|
-
|
|
248
|
-
\`\`\`typescript
|
|
249
|
-
import { defaultAnnotations, GCP } from "@intentius/chant-lexicon-gcp";
|
|
250
|
-
|
|
251
|
-
export const annotations = defaultAnnotations({
|
|
252
|
-
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
253
|
-
});
|
|
254
|
-
\`\`\`
|
|
255
|
-
|
|
256
|
-
This injects the project annotation into every resource. Without it, Config Connector uses the namespace's default project.
|
|
257
|
-
|
|
258
|
-
## Reconciliation lifecycle
|
|
259
|
-
|
|
260
|
-
Config Connector resources go through a reconciliation lifecycle:
|
|
261
|
-
|
|
262
|
-
<Diagram name="config-connector-lifecycle" alt="Config Connector state machine: YAML applied to kubectl, then Pending → Reconciling → UpToDate, UpdateFailed, or DependencyNotReady with retry paths" caption="Config Connector reconciliation lifecycle" />
|
|
263
|
-
|
|
264
|
-
| Status | Meaning |
|
|
265
|
-
|--------|---------|
|
|
266
|
-
| UpToDate | Resource matches desired state |
|
|
267
|
-
| Updating | Controller is applying changes |
|
|
268
|
-
| UpdateFailed | GCP API returned an error |
|
|
269
|
-
| DependencyNotReady | Waiting for a referenced resource |
|
|
270
|
-
| DeletionFailed | Cannot delete the GCP resource |
|
|
271
|
-
|
|
272
|
-
Check status with: \`kubectl get gcp -A\` or \`kubectl describe <resource>\`
|
|
273
|
-
|
|
274
|
-
## Default labels and annotations
|
|
275
|
-
|
|
276
|
-
Use \`defaultLabels()\` and \`defaultAnnotations()\` to inject metadata into all resources:
|
|
277
|
-
|
|
278
|
-
\`\`\`typescript
|
|
279
|
-
import { defaultLabels, defaultAnnotations } from "@intentius/chant-lexicon-gcp";
|
|
280
|
-
|
|
281
|
-
export const labels = defaultLabels({
|
|
282
|
-
"app.kubernetes.io/managed-by": "chant",
|
|
283
|
-
"env": "production",
|
|
284
|
-
});
|
|
285
|
-
\`\`\`
|
|
286
|
-
|
|
287
|
-
Explicit labels on individual resources take precedence over defaults.`,
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
slug: "lint-rules",
|
|
291
|
-
title: "Lint Rules",
|
|
292
|
-
description: "Built-in lint rules and post-synth checks for GCP Config Connector manifests",
|
|
293
|
-
content: `The GCP lexicon ships lint rules that run during \`chant lint\` and post-synth checks that validate the serialized YAML after \`chant build\`.
|
|
294
|
-
|
|
295
|
-
## Lint rules
|
|
296
|
-
|
|
297
|
-
Lint rules analyze your TypeScript source code before build.
|
|
298
|
-
|
|
299
|
-
| Rule | Description |
|
|
300
|
-
|------|-------------|
|
|
301
|
-
| WGC001 | Hardcoded project ID in resource constructors |
|
|
302
|
-
| WGC002 | Hardcoded region in resource constructors |
|
|
303
|
-
| WGC003 | Public IAM member (allUsers/allAuthenticatedUsers) |
|
|
304
|
-
|
|
305
|
-
## Post-synth checks
|
|
306
|
-
|
|
307
|
-
Post-synth checks run against the serialized YAML after build.
|
|
308
|
-
|
|
309
|
-
### Security
|
|
310
|
-
|
|
311
|
-
| Rule | Description |
|
|
312
|
-
|------|-------------|
|
|
313
|
-
| WGC101 | Missing encryption on StorageBucket or SQLInstance |
|
|
314
|
-
| WGC102 | Public IAM member detected in output |
|
|
315
|
-
| WGC104 | Missing uniform bucket-level access |
|
|
316
|
-
| WGC105 | Cloud SQL with public 0.0.0.0/0 in authorizedNetworks |
|
|
317
|
-
| WGC109 | ComputeFirewall allowing all sources (0.0.0.0/0) |
|
|
318
|
-
| WGC110 | KMS CryptoKey without rotation period |
|
|
319
|
-
|
|
320
|
-
### Best practices
|
|
321
|
-
|
|
322
|
-
| Rule | Description |
|
|
323
|
-
|------|-------------|
|
|
324
|
-
| WGC103 | Missing project annotation (uses namespace default) |
|
|
325
|
-
| WGC106 | Missing deletion policy annotation |
|
|
326
|
-
| WGC107 | StorageBucket without versioning |
|
|
327
|
-
| WGC108 | SQLInstance without backup configuration |
|
|
328
|
-
| WGC201 | Missing managed-by label |
|
|
329
|
-
| WGC202 | GKE cluster without workload identity |
|
|
330
|
-
| WGC203 | GKE node pool with overly broad cloud-platform OAuth scope |
|
|
331
|
-
| WGC204 | ComputeInstance without shielded VM config |
|
|
332
|
-
|
|
333
|
-
### Correctness
|
|
334
|
-
|
|
335
|
-
| Rule | Description |
|
|
336
|
-
|------|-------------|
|
|
337
|
-
| WGC111 | Resource reference points to a name not defined in the output |
|
|
338
|
-
| WGC112 | Config Connector resource has missing or invalid apiVersion |
|
|
339
|
-
| WGC113 | Config Connector resource uses an alpha API version |
|
|
340
|
-
|
|
341
|
-
### Schema validation
|
|
342
|
-
|
|
343
|
-
Checks each Config Connector resource's \`spec\` against the CRD schema it is
|
|
344
|
-
generated from.
|
|
345
|
-
|
|
346
|
-
| Rule | Description |
|
|
347
|
-
|------|-------------|
|
|
348
|
-
| WGC401 | Config Connector resource spec contains unknown field |
|
|
349
|
-
| WGC402 | Config Connector resource is missing a required spec field |
|
|
350
|
-
| WGC403 | Config Connector resource spec field has wrong type or structure |
|
|
351
|
-
|
|
352
|
-
### Compliance
|
|
353
|
-
|
|
354
|
-
| Rule | Description |
|
|
355
|
-
|------|-------------|
|
|
356
|
-
| WGC301 | No IAMAuditConfig resource in output |
|
|
357
|
-
| WGC302 | No Service (API enablement) resource in output |
|
|
358
|
-
| WGC303 | No VPC Service Controls perimeter |
|
|
359
|
-
|
|
360
|
-
## Running lint
|
|
361
|
-
|
|
362
|
-
\`\`\`bash
|
|
363
|
-
# Lint your chant project
|
|
364
|
-
chant lint
|
|
365
|
-
|
|
366
|
-
# Build (also runs post-synth checks)
|
|
367
|
-
chant build
|
|
368
|
-
\`\`\`
|
|
369
|
-
|
|
370
|
-
To suppress a rule on a specific line:
|
|
371
|
-
|
|
372
|
-
\`\`\`typescript
|
|
373
|
-
// chant-disable-next-line WGC001
|
|
374
|
-
const bucket = new StorageBucket({ metadata: { annotations: { "cnrm.cloud.google.com/project-id": "my-project" } } });
|
|
375
|
-
\`\`\``,
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
slug: "examples",
|
|
379
|
-
title: "Examples: Resources",
|
|
380
|
-
description: "GCP Config Connector resource examples — StorageBucket, ComputeInstance, CloudSQL, IAM",
|
|
381
|
-
content: `## StorageBucket
|
|
382
|
-
|
|
383
|
-
A Storage bucket with encryption, versioning, and lifecycle rules:
|
|
384
|
-
|
|
385
|
-
\`\`\`typescript
|
|
386
|
-
import { StorageBucket, GCP } from "@intentius/chant-lexicon-gcp";
|
|
387
|
-
|
|
388
|
-
export const bucket = new StorageBucket({
|
|
389
|
-
location: "US",
|
|
390
|
-
storageClass: "STANDARD",
|
|
391
|
-
uniformBucketLevelAccess: true,
|
|
392
|
-
versioning: { enabled: true },
|
|
393
|
-
encryption: {
|
|
394
|
-
defaultKmsKeyName: "projects/p/locations/us/keyRings/kr/cryptoKeys/key",
|
|
395
|
-
},
|
|
396
|
-
lifecycleRule: [
|
|
397
|
-
{ action: { type: "Delete" }, condition: { age: 365 } },
|
|
398
|
-
{ action: { type: "SetStorageClass", storageClass: "NEARLINE" }, condition: { age: 30 } },
|
|
399
|
-
],
|
|
400
|
-
});
|
|
401
|
-
\`\`\`
|
|
402
|
-
|
|
403
|
-
## ComputeInstance
|
|
404
|
-
|
|
405
|
-
A Compute Engine VM with shielded VM configuration:
|
|
406
|
-
|
|
407
|
-
\`\`\`typescript
|
|
408
|
-
import { ComputeInstance, GCP } from "@intentius/chant-lexicon-gcp";
|
|
409
|
-
|
|
410
|
-
export const vm = new ComputeInstance({
|
|
411
|
-
machineType: "e2-medium",
|
|
412
|
-
zone: "us-central1-a",
|
|
413
|
-
bootDisk: {
|
|
414
|
-
initializeParams: {
|
|
415
|
-
sourceImageRef: {
|
|
416
|
-
external: "projects/debian-cloud/global/images/debian-12",
|
|
417
|
-
},
|
|
418
|
-
},
|
|
419
|
-
},
|
|
420
|
-
networkInterface: [{
|
|
421
|
-
networkRef: { name: "my-network" },
|
|
422
|
-
subnetworkRef: { name: "my-subnet" },
|
|
423
|
-
}],
|
|
424
|
-
shieldedInstanceConfig: {
|
|
425
|
-
enableSecureBoot: true,
|
|
426
|
-
enableVtpm: true,
|
|
427
|
-
enableIntegrityMonitoring: true,
|
|
428
|
-
},
|
|
429
|
-
});
|
|
430
|
-
\`\`\`
|
|
431
|
-
|
|
432
|
-
## Cloud SQL
|
|
433
|
-
|
|
434
|
-
A PostgreSQL instance with backups and high availability:
|
|
435
|
-
|
|
436
|
-
\`\`\`typescript
|
|
437
|
-
import { CloudSqlInstance } from "@intentius/chant-lexicon-gcp";
|
|
438
|
-
|
|
439
|
-
const { instance, database, user } = CloudSqlInstance({
|
|
440
|
-
name: "app-db",
|
|
441
|
-
databaseVersion: "POSTGRES_15",
|
|
442
|
-
tier: "db-custom-2-8192",
|
|
443
|
-
region: "us-central1",
|
|
444
|
-
backupEnabled: true,
|
|
445
|
-
highAvailability: true,
|
|
446
|
-
diskSize: 50,
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
export { instance, database, user };
|
|
450
|
-
\`\`\`
|
|
451
|
-
|
|
452
|
-
## IAM Binding
|
|
453
|
-
|
|
454
|
-
Grant a service account access to a resource:
|
|
455
|
-
|
|
456
|
-
\`\`\`typescript
|
|
457
|
-
import { IAMPolicyMember } from "@intentius/chant-lexicon-gcp";
|
|
458
|
-
|
|
459
|
-
export const binding = new IAMPolicyMember({
|
|
460
|
-
member: "serviceAccount:app@my-project.iam.gserviceaccount.com",
|
|
461
|
-
role: "roles/storage.objectViewer",
|
|
462
|
-
resourceRef: {
|
|
463
|
-
apiVersion: "storage.cnrm.cloud.google.com/v1beta1",
|
|
464
|
-
kind: "StorageBucket",
|
|
465
|
-
name: "my-bucket",
|
|
466
|
-
},
|
|
467
|
-
});
|
|
468
|
-
\`\`\``,
|
|
469
|
-
},
|
|
470
|
-
{
|
|
471
|
-
slug: "composite-examples",
|
|
472
|
-
title: "Examples: Composites",
|
|
473
|
-
description: "All 10 GCP composites with full code and deployment workflow",
|
|
474
|
-
content: `Composites are higher-level constructs that produce multiple coordinated Config Connector resources from a single function call.
|
|
475
|
-
|
|
476
|
-
## GkeCluster
|
|
477
|
-
|
|
478
|
-
GKE cluster with node pool and workload identity:
|
|
479
|
-
|
|
480
|
-
\`\`\`typescript
|
|
481
|
-
import { GkeCluster } from "@intentius/chant-lexicon-gcp";
|
|
482
|
-
|
|
483
|
-
const { cluster, nodePool } = GkeCluster({
|
|
484
|
-
name: "my-cluster",
|
|
485
|
-
location: "us-central1",
|
|
486
|
-
machineType: "e2-standard-4",
|
|
487
|
-
minNodeCount: 1,
|
|
488
|
-
maxNodeCount: 10,
|
|
489
|
-
workloadIdentity: true,
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
export { cluster, nodePool };
|
|
493
|
-
\`\`\`
|
|
494
|
-
|
|
495
|
-
## CloudRunService
|
|
496
|
-
|
|
497
|
-
Cloud Run service with optional public access:
|
|
498
|
-
|
|
499
|
-
\`\`\`typescript
|
|
500
|
-
import { CloudRunService } from "@intentius/chant-lexicon-gcp";
|
|
501
|
-
|
|
502
|
-
const { service, publicIam } = CloudRunService({
|
|
503
|
-
name: "my-api",
|
|
504
|
-
image: "gcr.io/my-project/api:1.0",
|
|
505
|
-
port: 8080,
|
|
506
|
-
publicAccess: true,
|
|
507
|
-
minInstanceCount: 1,
|
|
508
|
-
maxInstanceCount: 10,
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
export { service, publicIam };
|
|
512
|
-
\`\`\`
|
|
513
|
-
|
|
514
|
-
## CloudSqlInstance
|
|
515
|
-
|
|
516
|
-
PostgreSQL with database and user:
|
|
517
|
-
|
|
518
|
-
\`\`\`typescript
|
|
519
|
-
import { CloudSqlInstance } from "@intentius/chant-lexicon-gcp";
|
|
520
|
-
|
|
521
|
-
const { instance, database, user } = CloudSqlInstance({
|
|
522
|
-
name: "app-db",
|
|
523
|
-
tier: "db-custom-2-8192",
|
|
524
|
-
backupEnabled: true,
|
|
525
|
-
highAvailability: true,
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
export { instance, database, user };
|
|
529
|
-
\`\`\`
|
|
530
|
-
|
|
531
|
-
## GcsBucket
|
|
532
|
-
|
|
533
|
-
Storage bucket with encryption and lifecycle:
|
|
534
|
-
|
|
535
|
-
\`\`\`typescript
|
|
536
|
-
import { GcsBucket } from "@intentius/chant-lexicon-gcp";
|
|
537
|
-
|
|
538
|
-
const { bucket } = GcsBucket({
|
|
539
|
-
name: "data-lake",
|
|
540
|
-
location: "US",
|
|
541
|
-
versioning: true,
|
|
542
|
-
kmsKeyName: "projects/p/locations/us/keyRings/kr/cryptoKeys/key",
|
|
543
|
-
lifecycleDeleteAfterDays: 365,
|
|
544
|
-
lifecycleNearlineAfterDays: 30,
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
export { bucket };
|
|
548
|
-
\`\`\`
|
|
549
|
-
|
|
550
|
-
## VpcNetwork
|
|
551
|
-
|
|
552
|
-
VPC with subnets, firewalls, and Cloud NAT:
|
|
553
|
-
|
|
554
|
-
\`\`\`typescript
|
|
555
|
-
import { VpcNetwork } from "@intentius/chant-lexicon-gcp";
|
|
556
|
-
|
|
557
|
-
const { network, subnets, firewalls, router, routerNat } = VpcNetwork({
|
|
558
|
-
name: "production",
|
|
559
|
-
subnets: [
|
|
560
|
-
{ name: "app", ipCidrRange: "10.0.0.0/24", region: "us-central1" },
|
|
561
|
-
{ name: "data", ipCidrRange: "10.0.1.0/24", region: "us-central1" },
|
|
562
|
-
],
|
|
563
|
-
enableNat: true,
|
|
564
|
-
natRegion: "us-central1",
|
|
565
|
-
allowIapSsh: true,
|
|
566
|
-
});
|
|
567
|
-
|
|
568
|
-
export { network, subnets, firewalls, router, routerNat };
|
|
569
|
-
\`\`\`
|
|
570
|
-
|
|
571
|
-
## PubSubPipeline
|
|
572
|
-
|
|
573
|
-
Topic + Subscription + optional dead-letter queue:
|
|
574
|
-
|
|
575
|
-
\`\`\`typescript
|
|
576
|
-
import { PubSubPipeline } from "@intentius/chant-lexicon-gcp";
|
|
577
|
-
|
|
578
|
-
const { topic, subscription, deadLetterTopic, subscriberIam } = PubSubPipeline({
|
|
579
|
-
name: "order-events",
|
|
580
|
-
enableDeadLetterQueue: true,
|
|
581
|
-
maxDeliveryAttempts: 5,
|
|
582
|
-
subscriberServiceAccount: "worker@my-project.iam.gserviceaccount.com",
|
|
583
|
-
});
|
|
584
|
-
|
|
585
|
-
export { topic, subscription, deadLetterTopic, subscriberIam };
|
|
586
|
-
\`\`\`
|
|
587
|
-
|
|
588
|
-
## CloudFunctionWithTrigger
|
|
589
|
-
|
|
590
|
-
Cloud Function + source bucket + optional public invoker IAM:
|
|
591
|
-
|
|
592
|
-
\`\`\`typescript
|
|
593
|
-
import { CloudFunctionWithTrigger } from "@intentius/chant-lexicon-gcp";
|
|
594
|
-
|
|
595
|
-
const { function: fn, sourceBucket, invokerIam } = CloudFunctionWithTrigger({
|
|
596
|
-
name: "process-upload",
|
|
597
|
-
runtime: "nodejs20",
|
|
598
|
-
entryPoint: "handler",
|
|
599
|
-
triggerType: "pubsub",
|
|
600
|
-
triggerTopic: "file-uploads",
|
|
601
|
-
region: "us-central1",
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
export { fn, sourceBucket, invokerIam };
|
|
605
|
-
\`\`\`
|
|
606
|
-
|
|
607
|
-
## PrivateService
|
|
608
|
-
|
|
609
|
-
Private service networking (VPC peering):
|
|
610
|
-
|
|
611
|
-
\`\`\`typescript
|
|
612
|
-
import { PrivateService } from "@intentius/chant-lexicon-gcp";
|
|
613
|
-
|
|
614
|
-
const { globalAddress, serviceConnection, dnsZone } = PrivateService({
|
|
615
|
-
name: "db-peering",
|
|
616
|
-
networkName: "production",
|
|
617
|
-
enableDns: true,
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
export { globalAddress, serviceConnection, dnsZone };
|
|
621
|
-
\`\`\`
|
|
622
|
-
|
|
623
|
-
## ManagedCertificate
|
|
624
|
-
|
|
625
|
-
Google-managed SSL certificate + optional HTTPS proxy:
|
|
626
|
-
|
|
627
|
-
\`\`\`typescript
|
|
628
|
-
import { ManagedCertificate } from "@intentius/chant-lexicon-gcp";
|
|
629
|
-
|
|
630
|
-
const { certificate, targetHttpsProxy, urlMap } = ManagedCertificate({
|
|
631
|
-
name: "web-cert",
|
|
632
|
-
domains: ["example.com", "www.example.com"],
|
|
633
|
-
createProxy: true,
|
|
634
|
-
backendServiceName: "web-backend",
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
export { certificate, targetHttpsProxy, urlMap };
|
|
638
|
-
\`\`\`
|
|
639
|
-
|
|
640
|
-
## SecureProject
|
|
641
|
-
|
|
642
|
-
Project with audit logging, API enablement, and IAM:
|
|
643
|
-
|
|
644
|
-
\`\`\`typescript
|
|
645
|
-
import { SecureProject } from "@intentius/chant-lexicon-gcp";
|
|
646
|
-
|
|
647
|
-
const { project, auditConfig, services, ownerIam, loggingSink } = SecureProject({
|
|
648
|
-
name: "my-project",
|
|
649
|
-
orgId: "123456789",
|
|
650
|
-
billingAccountRef: "ABCDEF-123456-ABCDEF",
|
|
651
|
-
owner: "user:admin@example.com",
|
|
652
|
-
loggingSinkDestination: "bigquery.googleapis.com/projects/audit/datasets/logs",
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
export { project, auditConfig, services, ownerIam, loggingSink };
|
|
656
|
-
\`\`\`
|
|
657
|
-
|
|
658
|
-
## Deploying composites
|
|
659
|
-
|
|
660
|
-
\`\`\`bash
|
|
661
|
-
# Build YAML manifests
|
|
662
|
-
chant build src/ --output manifests.yaml
|
|
663
|
-
|
|
664
|
-
# Lint for common issues
|
|
665
|
-
chant lint src/
|
|
666
|
-
|
|
667
|
-
# Dry run
|
|
668
|
-
kubectl apply -f manifests.yaml --dry-run=server
|
|
669
|
-
|
|
670
|
-
# Apply
|
|
671
|
-
kubectl apply -f manifests.yaml
|
|
672
|
-
\`\`\``,
|
|
673
|
-
},
|
|
674
|
-
{
|
|
675
|
-
slug: "operational-playbook",
|
|
676
|
-
title: "Operational Playbook",
|
|
677
|
-
description: "Build, lint, apply, troubleshoot Config Connector resources",
|
|
678
|
-
content: `This playbook covers the full lifecycle of chant-produced Config Connector manifests.
|
|
679
|
-
|
|
680
|
-
## Build & validate
|
|
681
|
-
|
|
682
|
-
| Step | Command | What it catches |
|
|
683
|
-
|------|---------|-----------------|
|
|
684
|
-
| Lint source | \`chant lint src/\` | Hardcoded project IDs (WGC001), regions (WGC002), public IAM (WGC003) |
|
|
685
|
-
| Build manifests | \`chant build src/ --output manifests.yaml\` | Post-synth: missing encryption (WGC101), public IAM (WGC102), missing project annotation (WGC103), 14 more checks |
|
|
686
|
-
| Server dry-run | \`kubectl apply -f manifests.yaml --dry-run=server\` | K8s API validation: CRD schema errors, admission webhooks |
|
|
687
|
-
|
|
688
|
-
## Deploy to Kubernetes
|
|
689
|
-
|
|
690
|
-
\`\`\`bash
|
|
691
|
-
# Build
|
|
692
|
-
chant build src/ --output manifests.yaml
|
|
693
|
-
|
|
694
|
-
# Diff before applying
|
|
695
|
-
kubectl diff -f manifests.yaml
|
|
696
|
-
|
|
697
|
-
# Dry run
|
|
698
|
-
kubectl apply -f manifests.yaml --dry-run=server
|
|
699
|
-
|
|
700
|
-
# Apply
|
|
701
|
-
kubectl apply -f manifests.yaml
|
|
702
|
-
\`\`\`
|
|
703
|
-
|
|
704
|
-
## Monitoring reconciliation
|
|
705
|
-
|
|
706
|
-
\`\`\`bash
|
|
707
|
-
# List all Config Connector resources
|
|
708
|
-
kubectl get gcp -A
|
|
709
|
-
|
|
710
|
-
# Check specific resource status
|
|
711
|
-
kubectl describe storagebuckets.storage.cnrm.cloud.google.com my-bucket
|
|
712
|
-
|
|
713
|
-
# Watch for status changes
|
|
714
|
-
kubectl get gcp -A -w
|
|
715
|
-
\`\`\`
|
|
716
|
-
|
|
717
|
-
## Troubleshooting
|
|
718
|
-
|
|
719
|
-
| Status | Meaning | Diagnostic | Fix |
|
|
720
|
-
|--------|---------|------------|-----|
|
|
721
|
-
| UpToDate | Resource in sync | None needed | — |
|
|
722
|
-
| Updating | Applying changes | \`kubectl describe\` → Events | Wait for completion |
|
|
723
|
-
| UpdateFailed | GCP API error | \`kubectl describe\` → Events | Check IAM permissions, quota, API enablement |
|
|
724
|
-
| DependencyNotReady | Waiting for ref | \`kubectl get gcp\` | Ensure referenced resource exists and is UpToDate |
|
|
725
|
-
| DeletionFailed | Cannot delete | \`kubectl describe\` → Events | Check IAM permissions, child resource dependencies |
|
|
726
|
-
|
|
727
|
-
## Common issues
|
|
728
|
-
|
|
729
|
-
| Symptom | Cause | Resolution |
|
|
730
|
-
|---------|-------|------------|
|
|
731
|
-
| Resource stuck in Updating | Missing GCP API | Enable API: add Service resource or \`gcloud services enable\` |
|
|
732
|
-
| Permission denied | Service account lacks IAM role | Grant role to Config Connector SA |
|
|
733
|
-
| Resource recreated on every apply | Missing deletion-policy annotation | Add \`cnrm.cloud.google.com/deletion-policy: abandon\` |
|
|
734
|
-
| Namespace not found | ConfigConnectorContext missing | Create ConfigConnectorContext in namespace |
|
|
735
|
-
| Cross-project reference fails | Missing project annotation | Add \`cnrm.cloud.google.com/project-id\` annotation |
|
|
736
|
-
|
|
737
|
-
## Quick reference
|
|
738
|
-
|
|
739
|
-
| Command | Description |
|
|
740
|
-
|---------|-------------|
|
|
741
|
-
| \`chant build src/\` | Synthesize manifests |
|
|
742
|
-
| \`chant lint src/\` | Check for anti-patterns |
|
|
743
|
-
| \`kubectl apply -f manifests.yaml\` | Apply to cluster |
|
|
744
|
-
| \`kubectl get gcp -A\` | List all Config Connector resources |
|
|
745
|
-
| \`kubectl describe <resource>\` | Check reconciliation status |
|
|
746
|
-
| \`kubectl delete -f manifests.yaml\` | Remove resources |`,
|
|
747
|
-
},
|
|
748
|
-
{
|
|
749
|
-
slug: "importing-yaml",
|
|
750
|
-
title: "Importing Existing YAML",
|
|
751
|
-
description: "Convert existing Config Connector YAML into typed TypeScript",
|
|
752
|
-
content: `Chant can parse existing Config Connector YAML manifests and generate typed TypeScript source files.
|
|
753
|
-
|
|
754
|
-
## How it works
|
|
755
|
-
|
|
756
|
-
\`\`\`
|
|
757
|
-
Input YAML → parse → generate TypeScript → export typed resources
|
|
758
|
-
\`\`\`
|
|
759
|
-
|
|
760
|
-
The importer reads multi-document YAML, identifies Config Connector resources by their \`cnrm.cloud.google.com\` apiVersion, and generates corresponding typed constructor calls.
|
|
761
|
-
|
|
762
|
-
## Example
|
|
763
|
-
|
|
764
|
-
Input YAML:
|
|
765
|
-
|
|
766
|
-
\`\`\`yaml
|
|
767
|
-
apiVersion: storage.cnrm.cloud.google.com/v1beta1
|
|
768
|
-
kind: StorageBucket
|
|
769
|
-
metadata:
|
|
770
|
-
name: my-bucket
|
|
771
|
-
spec:
|
|
772
|
-
location: US
|
|
773
|
-
uniformBucketLevelAccess: true
|
|
774
|
-
\`\`\`
|
|
775
|
-
|
|
776
|
-
Generated TypeScript:
|
|
777
|
-
|
|
778
|
-
\`\`\`typescript
|
|
779
|
-
import { Bucket } from "@intentius/chant-lexicon-gcp";
|
|
780
|
-
|
|
781
|
-
export const myBucket = new Bucket({
|
|
782
|
-
metadata: { name: "my-bucket" },
|
|
783
|
-
location: "US",
|
|
784
|
-
uniformBucketLevelAccess: true,
|
|
785
|
-
});
|
|
786
|
-
\`\`\`
|
|
787
|
-
|
|
788
|
-
## Limitations
|
|
789
|
-
|
|
790
|
-
The import pipeline:
|
|
791
|
-
|
|
792
|
-
- Only handles Config Connector resources (\`cnrm.cloud.google.com\` apiVersion)
|
|
793
|
-
- Non-CC resources (standard K8s Deployments, Services) are filtered out
|
|
794
|
-
- Resource references are preserved as literal values, not typed refs
|
|
795
|
-
- Multi-document YAML is fully supported`,
|
|
796
|
-
},
|
|
797
|
-
{
|
|
798
|
-
slug: "skills",
|
|
799
|
-
title: "AI Skills",
|
|
800
|
-
description: "AI agent skills bundled with the GCP lexicon",
|
|
801
|
-
content: `The GCP lexicon ships an AI skill called **chant-gcp** that teaches AI coding agents how to build, validate, and deploy Config Connector manifests from a chant project.
|
|
802
|
-
|
|
803
|
-
## What are skills?
|
|
804
|
-
|
|
805
|
-
Skills are structured markdown documents bundled with a lexicon. When an AI agent works in a chant project, it discovers and loads relevant skills automatically.
|
|
806
|
-
|
|
807
|
-
## Installation
|
|
808
|
-
|
|
809
|
-
When you scaffold a new project with \`chant init --lexicon gcp\`, the skill is installed to \`skills/chant-gcp/SKILL.md\`.
|
|
810
|
-
|
|
811
|
-
## Skill: chant-gcp
|
|
812
|
-
|
|
813
|
-
The \`chant-gcp\` skill covers:
|
|
814
|
-
|
|
815
|
-
- **Build** — \`chant build src/ --output manifests.yaml\`
|
|
816
|
-
- **Lint** — \`chant lint src/\` + 23 post-synth checks
|
|
817
|
-
- **Apply** — \`kubectl apply -f manifests.yaml\`
|
|
818
|
-
- **Status** — \`kubectl get gcp -A\`
|
|
819
|
-
- **Troubleshooting** — reconciliation status, events, common error patterns
|
|
820
|
-
|
|
821
|
-
## MCP integration
|
|
822
|
-
|
|
823
|
-
| MCP tool | Description |
|
|
824
|
-
|----------|-------------|
|
|
825
|
-
| \`diff\` | Compare current build output against previous |
|
|
826
|
-
|
|
827
|
-
| MCP resource | Description |
|
|
828
|
-
|--------------|-------------|
|
|
829
|
-
| \`resource-catalog\` | JSON list of all supported Config Connector resource types |
|
|
830
|
-
| \`examples/basic-bucket\` | Example StorageBucket code |`,
|
|
831
|
-
},
|
|
832
|
-
],
|
|
833
|
-
// `lint-rules` is gcp's rules documentation, so the generated `rules`
|
|
834
|
-
// table is a duplicate — and buildSidebar already declines to link it when
|
|
835
|
-
// a `lint-rules` page exists, which left it emitted but unreachable
|
|
836
|
-
// (#1312). aws, k8s, gitlab and github suppress it for the same reason.
|
|
837
|
-
sidebarExtra: [
|
|
838
|
-
{ label: "Deploying to GKE", slug: "gke-kubernetes" },
|
|
839
|
-
],
|
|
840
114
|
};
|
|
841
115
|
|
|
842
116
|
const result = docsPipeline(config);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc101 } from "./wgc101";
|
|
3
4
|
import { wgc102 } from "./wgc102";
|
|
4
5
|
import { wgc103 } from "./wgc103";
|
|
@@ -24,9 +25,7 @@ import { wgc402 } from "./wgc402";
|
|
|
24
25
|
import { wgc403 } from "./wgc403";
|
|
25
26
|
|
|
26
27
|
function makeCtx(yaml: string) {
|
|
27
|
-
return
|
|
28
|
-
outputs: new Map([["gcp", yaml]]),
|
|
29
|
-
};
|
|
28
|
+
return makePostSynthCtx("gcp", yaml);
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
// ── WGC101: Missing encryption ─────────────────────────────────────
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc101 } from "./wgc101";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC101: missing encryption", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc102 } from "./wgc102";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC102: public IAM in output", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc103 } from "./wgc103";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC103: missing project annotation", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc104 } from "./wgc104";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC104: missing uniform bucket access", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc105 } from "./wgc105";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC105: public Cloud SQL", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc106 } from "./wgc106";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC106: missing deletion policy", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc107 } from "./wgc107";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC107: missing versioning", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc108 } from "./wgc108";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC108: missing backup configuration", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc109 } from "./wgc109";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC109: open firewall", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc110 } from "./wgc110";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC110: missing key rotation", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc111 } from "./wgc111";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC111: dangling resource reference", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc112 } from "./wgc112";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC112: missing or invalid apiVersion", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc113 } from "./wgc113";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC113: alpha API version", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc201 } from "./wgc201";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC201: missing managed-by label", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc202 } from "./wgc202";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC202: missing workload identity", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc203 } from "./wgc203";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC203: cloud-platform OAuth scope", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc204 } from "./wgc204";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC204: missing shielded VM config", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc301 } from "./wgc301";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC301: no audit logging", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc302 } from "./wgc302";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC302: service API not enabled", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc303 } from "./wgc303";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC303: missing VPC Service Controls", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc401 } from "./wgc401";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC401: unknown spec field", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc402 } from "./wgc402";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC402: missing required field", () => {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
2
3
|
import { wgc403 } from "./wgc403";
|
|
3
4
|
|
|
4
5
|
function makeCtx(yaml: string) {
|
|
5
|
-
return
|
|
6
|
-
outputs: new Map([["gcp", yaml]]),
|
|
7
|
-
};
|
|
6
|
+
return makePostSynthCtx("gcp", yaml);
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
describe("WGC403: type/structure mismatch", () => {
|
package/src/serializer.test.ts
CHANGED
|
@@ -216,7 +216,7 @@ describe("gcpSerializer", () => {
|
|
|
216
216
|
}),
|
|
217
217
|
);
|
|
218
218
|
|
|
219
|
-
const result = gcpSerializer.serialize(entities);
|
|
219
|
+
const result = gcpSerializer.serialize(entities) as string;
|
|
220
220
|
expect(result).toContain("env: prod");
|
|
221
221
|
// Should not contain "dev" since explicit overrides
|
|
222
222
|
const envLines = result.split("\n").filter((l: string) => l.includes("env:"));
|
|
@@ -233,7 +233,7 @@ describe("gcpSerializer", () => {
|
|
|
233
233
|
}),
|
|
234
234
|
);
|
|
235
235
|
|
|
236
|
-
const result = gcpSerializer.serialize(entities);
|
|
236
|
+
const result = gcpSerializer.serialize(entities) as string;
|
|
237
237
|
// Only one document — property entities should not appear as separate docs
|
|
238
238
|
expect(result.split("---").length).toBeLessThanOrEqual(2);
|
|
239
239
|
});
|
|
@@ -264,7 +264,7 @@ describe("gcpSerializer", () => {
|
|
|
264
264
|
}),
|
|
265
265
|
);
|
|
266
266
|
|
|
267
|
-
const result = gcpSerializer.serialize(entities);
|
|
267
|
+
const result = gcpSerializer.serialize(entities) as string;
|
|
268
268
|
const lines = result.split("\n");
|
|
269
269
|
const keyLines = lines.filter((l: string) => /^\w+:/.test(l));
|
|
270
270
|
const keys = keyLines.map((l: string) => l.split(":")[0]);
|