@intentius/chant-lexicon-gcp 0.0.18 → 0.0.24
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/integrity.json +12 -8
- package/dist/manifest.json +1 -1
- package/dist/meta.json +18141 -0
- package/dist/rules/schema-registry.ts +91 -0
- package/dist/rules/wgc101.ts +1 -1
- package/dist/rules/wgc401.ts +59 -0
- package/dist/rules/wgc402.ts +54 -0
- package/dist/rules/wgc403.ts +84 -0
- package/dist/skills/{chant-gke.md → chant-gcp-gke.md} +1 -1
- package/dist/skills/chant-gcp-patterns.md +3 -2
- package/dist/skills/chant-gcp-security.md +3 -2
- package/dist/skills/chant-gcp.md +363 -28
- package/package.json +20 -2
- package/src/codegen/docs.test.ts +16 -0
- package/src/codegen/generate.test.ts +18 -0
- package/src/codegen/generate.ts +11 -0
- package/src/codegen/package.test.ts +16 -0
- package/src/composites/cloud-function.ts +23 -15
- package/src/composites/cloud-run-service.ts +20 -13
- package/src/composites/cloud-sql-instance.ts +18 -14
- package/src/composites/composites.test.ts +94 -62
- package/src/composites/gcs-bucket.ts +13 -9
- package/src/composites/gke-cluster.ts +91 -16
- package/src/composites/index.ts +11 -11
- package/src/composites/managed-certificate.ts +19 -15
- package/src/composites/private-service.ts +23 -15
- package/src/composites/pubsub-pipeline.ts +30 -18
- package/src/composites/secure-project.ts +42 -27
- package/src/composites/vpc-network.ts +42 -35
- package/src/generated/lexicon-gcp.json +18141 -0
- package/src/import/import-fixtures.test.ts +98 -0
- package/src/index.ts +11 -11
- package/src/lint/post-synth/gcp-helpers.test.ts +166 -0
- package/src/lint/post-synth/post-synth.test.ts +132 -1
- package/src/lint/post-synth/schema-registry.ts +91 -0
- package/src/lint/post-synth/wgc101.test.ts +40 -0
- package/src/lint/post-synth/wgc101.ts +1 -1
- package/src/lint/post-synth/wgc102.test.ts +38 -0
- package/src/lint/post-synth/wgc103.test.ts +38 -0
- package/src/lint/post-synth/wgc104.test.ts +37 -0
- package/src/lint/post-synth/wgc105.test.ts +46 -0
- package/src/lint/post-synth/wgc106.test.ts +38 -0
- package/src/lint/post-synth/wgc107.test.ts +38 -0
- package/src/lint/post-synth/wgc108.test.ts +42 -0
- package/src/lint/post-synth/wgc109.test.ts +46 -0
- package/src/lint/post-synth/wgc110.test.ts +37 -0
- package/src/lint/post-synth/wgc111.test.ts +46 -0
- package/src/lint/post-synth/wgc112.test.ts +48 -0
- package/src/lint/post-synth/wgc113.test.ts +36 -0
- package/src/lint/post-synth/wgc201.test.ts +38 -0
- package/src/lint/post-synth/wgc202.test.ts +38 -0
- package/src/lint/post-synth/wgc203.test.ts +45 -0
- package/src/lint/post-synth/wgc204.test.ts +42 -0
- package/src/lint/post-synth/wgc301.test.ts +39 -0
- package/src/lint/post-synth/wgc302.test.ts +36 -0
- package/src/lint/post-synth/wgc303.test.ts +37 -0
- package/src/lint/post-synth/wgc401.test.ts +46 -0
- package/src/lint/post-synth/wgc401.ts +59 -0
- package/src/lint/post-synth/wgc402.test.ts +40 -0
- package/src/lint/post-synth/wgc402.ts +54 -0
- package/src/lint/post-synth/wgc403.test.ts +59 -0
- package/src/lint/post-synth/wgc403.ts +84 -0
- package/src/plugin.test.ts +4 -1
- package/src/plugin.ts +258 -177
- package/src/skills/{chant-gke.md → chant-gcp-gke.md} +1 -1
- package/src/skills/chant-gcp-patterns.md +3 -2
- package/src/skills/chant-gcp-security.md +3 -2
- package/src/skills/chant-gcp.md +363 -28
package/src/plugin.ts
CHANGED
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { createRequire } from "module";
|
|
9
|
-
import type { LexiconPlugin,
|
|
9
|
+
import type { LexiconPlugin, InitTemplateSet, ResourceMetadata } from "@intentius/chant/lexicon";
|
|
10
10
|
const require = createRequire(import.meta.url);
|
|
11
11
|
import type { LintRule } from "@intentius/chant/lint/rule";
|
|
12
|
-
import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
13
12
|
import type { TemplateParser } from "@intentius/chant/import/parser";
|
|
14
13
|
import type { TypeScriptGenerator } from "@intentius/chant/import/generator";
|
|
15
14
|
import type { CompletionContext, CompletionItem, HoverContext, HoverInfo } from "@intentius/chant/lsp/types";
|
|
16
|
-
import
|
|
15
|
+
import { discoverPostSynthChecks } from "@intentius/chant/lint/discover";
|
|
16
|
+
import { createSkillsLoader, createDiffTool, createCatalogResource } from "@intentius/chant/lexicon-plugin-helpers";
|
|
17
|
+
import { join, dirname } from "path";
|
|
18
|
+
import { fileURLToPath } from "url";
|
|
17
19
|
import { gcpSerializer } from "./serializer";
|
|
18
20
|
|
|
19
21
|
export const gcpPlugin: LexiconPlugin = {
|
|
@@ -27,33 +29,9 @@ export const gcpPlugin: LexiconPlugin = {
|
|
|
27
29
|
return [hardcodedProjectRule, hardcodedRegionRule, publicIamRule];
|
|
28
30
|
},
|
|
29
31
|
|
|
30
|
-
postSynthChecks()
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const { wgc103 } = require("./lint/post-synth/wgc103");
|
|
34
|
-
const { wgc104 } = require("./lint/post-synth/wgc104");
|
|
35
|
-
const { wgc105 } = require("./lint/post-synth/wgc105");
|
|
36
|
-
const { wgc106 } = require("./lint/post-synth/wgc106");
|
|
37
|
-
const { wgc107 } = require("./lint/post-synth/wgc107");
|
|
38
|
-
const { wgc108 } = require("./lint/post-synth/wgc108");
|
|
39
|
-
const { wgc109 } = require("./lint/post-synth/wgc109");
|
|
40
|
-
const { wgc110 } = require("./lint/post-synth/wgc110");
|
|
41
|
-
const { wgc201 } = require("./lint/post-synth/wgc201");
|
|
42
|
-
const { wgc202 } = require("./lint/post-synth/wgc202");
|
|
43
|
-
const { wgc203 } = require("./lint/post-synth/wgc203");
|
|
44
|
-
const { wgc204 } = require("./lint/post-synth/wgc204");
|
|
45
|
-
const { wgc301 } = require("./lint/post-synth/wgc301");
|
|
46
|
-
const { wgc302 } = require("./lint/post-synth/wgc302");
|
|
47
|
-
const { wgc303 } = require("./lint/post-synth/wgc303");
|
|
48
|
-
const { wgc111 } = require("./lint/post-synth/wgc111");
|
|
49
|
-
const { wgc112 } = require("./lint/post-synth/wgc112");
|
|
50
|
-
const { wgc113 } = require("./lint/post-synth/wgc113");
|
|
51
|
-
return [
|
|
52
|
-
wgc101, wgc102, wgc103, wgc104, wgc105, wgc106, wgc107, wgc108, wgc109, wgc110,
|
|
53
|
-
wgc111, wgc112, wgc113,
|
|
54
|
-
wgc201, wgc202, wgc203, wgc204,
|
|
55
|
-
wgc301, wgc302, wgc303,
|
|
56
|
-
];
|
|
32
|
+
postSynthChecks() {
|
|
33
|
+
const postSynthDir = join(dirname(fileURLToPath(import.meta.url)), "lint", "post-synth");
|
|
34
|
+
return discoverPostSynthChecks(postSynthDir, import.meta.url);
|
|
57
35
|
},
|
|
58
36
|
|
|
59
37
|
intrinsics() {
|
|
@@ -87,10 +65,9 @@ export const annotations = defaultAnnotations({
|
|
|
87
65
|
export const cluster = new GKECluster({
|
|
88
66
|
location: GCP.Region,
|
|
89
67
|
initialNodeCount: 1,
|
|
90
|
-
removeDefaultNodePool: true,
|
|
91
68
|
releaseChannel: { channel: "REGULAR" },
|
|
92
69
|
workloadIdentityConfig: {
|
|
93
|
-
workloadPool:
|
|
70
|
+
workloadPool: \`\${GCP.ProjectId}.svc.id.goog\`,
|
|
94
71
|
},
|
|
95
72
|
});
|
|
96
73
|
|
|
@@ -111,6 +88,54 @@ export const nodePool = new NodePool({
|
|
|
111
88
|
};
|
|
112
89
|
}
|
|
113
90
|
|
|
91
|
+
if (template === "cloud-function") {
|
|
92
|
+
return {
|
|
93
|
+
src: {
|
|
94
|
+
"infra.ts": `/**
|
|
95
|
+
* Cloud Function with Pub/Sub trigger
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
import { CloudFunction, StorageBucket, GCPServiceAccount, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
|
|
99
|
+
import { defaultAnnotations } from "@intentius/chant-lexicon-gcp";
|
|
100
|
+
|
|
101
|
+
export const annotations = defaultAnnotations({
|
|
102
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export const sourceBucket = new StorageBucket({
|
|
106
|
+
location: GCP.Region,
|
|
107
|
+
storageClass: "STANDARD",
|
|
108
|
+
uniformBucketLevelAccess: true,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
export const functionSa = new GCPServiceAccount({
|
|
112
|
+
displayName: "Cloud Function Service Account",
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
export const fn = new CloudFunction({
|
|
116
|
+
location: GCP.Region,
|
|
117
|
+
runtime: "nodejs22",
|
|
118
|
+
entryPoint: "handler",
|
|
119
|
+
sourceArchiveBucket: sourceBucket,
|
|
120
|
+
sourceArchiveObject: "function-source.zip",
|
|
121
|
+
triggerHttp: true,
|
|
122
|
+
serviceAccountEmail: functionSa,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export const invoker = new IAMPolicyMember({
|
|
126
|
+
member: "allUsers",
|
|
127
|
+
role: "roles/cloudfunctions.invoker",
|
|
128
|
+
resourceRef: {
|
|
129
|
+
apiVersion: "cloudfunctions.cnrm.cloud.google.com/v1beta1",
|
|
130
|
+
kind: "CloudFunction",
|
|
131
|
+
name: fn,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
`,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
114
139
|
// Default: StorageBucket + IAMPolicyMember
|
|
115
140
|
return {
|
|
116
141
|
src: {
|
|
@@ -184,50 +209,131 @@ export const bucketReader = new IAMPolicyMember({
|
|
|
184
209
|
return gcpHover(ctx);
|
|
185
210
|
},
|
|
186
211
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
212
|
+
async describeResources(options: {
|
|
213
|
+
environment: string;
|
|
214
|
+
buildOutput: string;
|
|
215
|
+
entityNames: string[];
|
|
216
|
+
}): Promise<Record<string, ResourceMetadata>> {
|
|
217
|
+
const { getRuntime } = await import("@intentius/chant/runtime-adapter");
|
|
218
|
+
const rt = getRuntime();
|
|
219
|
+
const resources: Record<string, ResourceMetadata> = {};
|
|
220
|
+
|
|
221
|
+
// Convert TypeScript variable names to kebab-case manifest names
|
|
222
|
+
// (mirrors serializer.ts:165 metadata.name assignment)
|
|
223
|
+
function entityToManifestName(name: string): string {
|
|
224
|
+
return name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Detect namespace: prefer namespace from manifests, then kubectl context, fallback "default"
|
|
228
|
+
let namespace = "default";
|
|
229
|
+
try {
|
|
230
|
+
// Check manifests for an explicit namespace
|
|
231
|
+
const nsMatch = options.buildOutput.match(/^\s+namespace:\s*(.+)$/m);
|
|
232
|
+
if (nsMatch) {
|
|
233
|
+
namespace = nsMatch[1].trim();
|
|
234
|
+
} else {
|
|
235
|
+
// Try kubectl current context namespace
|
|
236
|
+
const nsResult = await rt.spawn([
|
|
237
|
+
"kubectl", "config", "view", "--minify", "-o", "jsonpath={..namespace}",
|
|
238
|
+
]);
|
|
239
|
+
if (nsResult.exitCode === 0 && nsResult.stdout.trim()) {
|
|
240
|
+
namespace = nsResult.stdout.trim();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
} catch (err) {
|
|
244
|
+
console.error(`[gcp] describeResources: namespace detection failed, using "default": ${err instanceof Error ? err.message : String(err)}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Parse build output to extract kind/name pairs
|
|
248
|
+
let manifests: Array<{ kind: string; name: string; apiVersion: string; namespace?: string }> = [];
|
|
249
|
+
try {
|
|
250
|
+
const docs = options.buildOutput.split(/^---$/m).filter((d) => d.trim());
|
|
251
|
+
for (const doc of docs) {
|
|
252
|
+
const kindMatch = doc.match(/^kind:\s*(.+)$/m);
|
|
253
|
+
const nameMatch = doc.match(/^\s+name:\s*(.+)$/m);
|
|
254
|
+
const apiVersionMatch = doc.match(/^apiVersion:\s*(.+)$/m);
|
|
255
|
+
if (kindMatch && nameMatch && apiVersionMatch) {
|
|
256
|
+
const nsMatch = doc.match(/^\s+namespace:\s*(.+)$/m);
|
|
257
|
+
manifests.push({
|
|
258
|
+
kind: kindMatch[1].trim(),
|
|
259
|
+
name: nameMatch[1].trim(),
|
|
260
|
+
apiVersion: apiVersionMatch[1].trim(),
|
|
261
|
+
...(nsMatch && { namespace: nsMatch[1].trim() }),
|
|
207
262
|
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.error(`[gcp] describeResources: failed to parse build output: ${err instanceof Error ? err.message : String(err)}`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
let resolved = 0;
|
|
270
|
+
|
|
271
|
+
for (const entityName of options.entityNames) {
|
|
272
|
+
const manifestName = entityToManifestName(entityName);
|
|
273
|
+
const manifest = manifests.find((m) => m.name === manifestName);
|
|
274
|
+
if (!manifest) {
|
|
275
|
+
console.error(`[gcp] describeResources: no manifest found for entity "${entityName}" (expected manifest name "${manifestName}")`);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const resourceNs = manifest.namespace ?? namespace;
|
|
280
|
+
const resourceType = manifest.kind.toLowerCase();
|
|
281
|
+
const getResult = await rt.spawn([
|
|
282
|
+
"kubectl", "get", resourceType, manifest.name,
|
|
283
|
+
"-n", resourceNs, "-o", "json",
|
|
284
|
+
]);
|
|
285
|
+
|
|
286
|
+
if (getResult.exitCode !== 0) {
|
|
287
|
+
console.error(`[gcp] describeResources: kubectl get ${resourceType} ${manifest.name} -n ${resourceNs} failed (exit ${getResult.exitCode}): ${getResult.stderr.trim()}`);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
const obj = JSON.parse(getResult.stdout) as {
|
|
293
|
+
metadata: { name: string; uid: string; creationTimestamp: string };
|
|
294
|
+
status?: {
|
|
295
|
+
conditions?: Array<{ type: string; status: string }>;
|
|
296
|
+
externalRef?: string;
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
let status = "Unknown";
|
|
301
|
+
if (obj.status?.conditions) {
|
|
302
|
+
const ready = obj.status.conditions.find((c) => c.type === "Ready");
|
|
303
|
+
status = ready?.status === "True" ? "Ready" : "NotReady";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const attributes: Record<string, unknown> = {
|
|
307
|
+
uid: obj.metadata.uid,
|
|
308
|
+
};
|
|
309
|
+
if (obj.status?.externalRef) {
|
|
310
|
+
attributes.externalRef = obj.status.externalRef;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
resources[entityName] = {
|
|
314
|
+
type: `${manifest.apiVersion}/${manifest.kind}`,
|
|
315
|
+
physicalId: obj.status?.externalRef ?? obj.metadata.name,
|
|
316
|
+
status,
|
|
317
|
+
lastUpdated: obj.metadata.creationTimestamp,
|
|
318
|
+
attributes,
|
|
319
|
+
};
|
|
320
|
+
resolved++;
|
|
321
|
+
} catch (err) {
|
|
322
|
+
console.error(`[gcp] describeResources: failed to parse kubectl output for "${entityName}": ${err instanceof Error ? err.message : String(err)}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
console.error(`[gcp] describeResources: ${resolved}/${options.entityNames.length} resources resolved`);
|
|
327
|
+
return resources;
|
|
212
328
|
},
|
|
213
329
|
|
|
214
|
-
|
|
330
|
+
mcpTools() {
|
|
331
|
+
return [createDiffTool(gcpSerializer, "Compare current build output against previous output for GCP Config Connector manifests")];
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
mcpResources() {
|
|
215
335
|
return [
|
|
216
|
-
|
|
217
|
-
uri: "resource-catalog",
|
|
218
|
-
name: "GCP Config Connector Resource Catalog",
|
|
219
|
-
description: "JSON list of all supported GCP Config Connector resource types",
|
|
220
|
-
mimeType: "application/json",
|
|
221
|
-
async handler(): Promise<string> {
|
|
222
|
-
const lexicon = require("./generated/lexicon-gcp.json") as Record<string, { resourceType: string; kind: string }>;
|
|
223
|
-
const entries = Object.entries(lexicon).map(([className, entry]) => ({
|
|
224
|
-
className,
|
|
225
|
-
resourceType: entry.resourceType,
|
|
226
|
-
kind: entry.kind,
|
|
227
|
-
}));
|
|
228
|
-
return JSON.stringify(entries);
|
|
229
|
-
},
|
|
230
|
-
},
|
|
336
|
+
createCatalogResource(import.meta.url, "GCP Config Connector Resource Catalog", "JSON list of all supported GCP Config Connector resource types", "lexicon-gcp.json"),
|
|
231
337
|
{
|
|
232
338
|
uri: "examples/basic-bucket",
|
|
233
339
|
name: "Basic GCS Bucket Example",
|
|
@@ -253,111 +359,86 @@ export const bucket = new StorageBucket({
|
|
|
253
359
|
];
|
|
254
360
|
},
|
|
255
361
|
|
|
256
|
-
skills
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
{
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
{
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
{
|
|
337
|
-
title: "Deploy GKE microservice",
|
|
338
|
-
input: "Deploy a GKE project end-to-end",
|
|
339
|
-
output: "npm run bootstrap && npm run deploy",
|
|
340
|
-
},
|
|
341
|
-
],
|
|
342
|
-
},
|
|
343
|
-
];
|
|
344
|
-
|
|
345
|
-
for (const skill of skillFiles) {
|
|
346
|
-
try {
|
|
347
|
-
const content = readFileSync(join(dir, "skills", skill.file), "utf-8");
|
|
348
|
-
skills.push({
|
|
349
|
-
name: skill.name,
|
|
350
|
-
description: skill.description,
|
|
351
|
-
content,
|
|
352
|
-
triggers: skill.triggers,
|
|
353
|
-
parameters: skill.parameters,
|
|
354
|
-
examples: skill.examples,
|
|
355
|
-
});
|
|
356
|
-
} catch { /* skip missing skills */ }
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
return skills;
|
|
360
|
-
},
|
|
362
|
+
skills: createSkillsLoader(import.meta.url, [
|
|
363
|
+
{
|
|
364
|
+
file: "chant-gcp.md",
|
|
365
|
+
name: "chant-gcp",
|
|
366
|
+
description: "Build, validate, and deploy GCP Config Connector manifests from a chant project",
|
|
367
|
+
triggers: [
|
|
368
|
+
{ type: "file-pattern" as const, value: "*.gcp.ts" },
|
|
369
|
+
{ type: "context" as const, value: "gcp" },
|
|
370
|
+
],
|
|
371
|
+
parameters: [
|
|
372
|
+
{
|
|
373
|
+
name: "resourceType",
|
|
374
|
+
type: "string",
|
|
375
|
+
description: "GCP Config Connector resource type to work with",
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
examples: [
|
|
379
|
+
{
|
|
380
|
+
title: "Create a Storage Bucket",
|
|
381
|
+
output: "new StorageBucket({ location: \"US\", storageClass: \"STANDARD\" })",
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
title: "Create a GKE Cluster",
|
|
385
|
+
output: "new GKECluster({ location: GCP.Region, releaseChannel: { channel: \"REGULAR\" } })",
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
file: "chant-gcp-security.md",
|
|
391
|
+
name: "chant-gcp-security",
|
|
392
|
+
description: "GCP security best practices for infrastructure",
|
|
393
|
+
triggers: [
|
|
394
|
+
{ type: "context" as const, value: "gcp security" },
|
|
395
|
+
{ type: "context" as const, value: "gcp iam" },
|
|
396
|
+
],
|
|
397
|
+
parameters: [],
|
|
398
|
+
examples: [
|
|
399
|
+
{
|
|
400
|
+
title: "Secure Storage Bucket",
|
|
401
|
+
input: "Create a storage bucket with encryption and uniform access",
|
|
402
|
+
output: "import { GcsBucket } from \"@intentius/chant-lexicon-gcp\";\n\nconst { bucket } = GcsBucket({ name: \"my-bucket\", kmsKeyName: \"...\" });",
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
file: "chant-gcp-patterns.md",
|
|
408
|
+
name: "chant-gcp-patterns",
|
|
409
|
+
description: "Advanced GCP Config Connector patterns",
|
|
410
|
+
triggers: [
|
|
411
|
+
{ type: "context" as const, value: "gcp patterns" },
|
|
412
|
+
{ type: "context" as const, value: "gcp composites" },
|
|
413
|
+
],
|
|
414
|
+
parameters: [],
|
|
415
|
+
examples: [
|
|
416
|
+
{
|
|
417
|
+
title: "VPC with Subnets",
|
|
418
|
+
input: "Create a VPC network with private subnets",
|
|
419
|
+
output: "import { VpcNetwork } from \"@intentius/chant-lexicon-gcp\";\n\nconst { network, subnets } = VpcNetwork({ name: \"my-vpc\", subnets: [...] });",
|
|
420
|
+
},
|
|
421
|
+
],
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
file: "chant-gcp-gke.md",
|
|
425
|
+
name: "chant-gcp-gke",
|
|
426
|
+
description: "End-to-end GKE workflow bridging GCP infrastructure and Kubernetes workloads",
|
|
427
|
+
triggers: [
|
|
428
|
+
{ type: "context" as const, value: "gke" },
|
|
429
|
+
{ type: "context" as const, value: "gcp kubernetes" },
|
|
430
|
+
{ type: "context" as const, value: "config connector" },
|
|
431
|
+
],
|
|
432
|
+
parameters: [],
|
|
433
|
+
examples: [
|
|
434
|
+
{
|
|
435
|
+
title: "Deploy GKE microservice",
|
|
436
|
+
input: "Deploy a GKE project end-to-end",
|
|
437
|
+
output: "npm run bootstrap && npm run deploy",
|
|
438
|
+
},
|
|
439
|
+
],
|
|
440
|
+
},
|
|
441
|
+
]),
|
|
361
442
|
|
|
362
443
|
async generate(options?: { verbose?: boolean }): Promise<void> {
|
|
363
444
|
const { generate, writeGeneratedFiles } = await import("./codegen/generate");
|