@intentius/chant-lexicon-gcp 0.124.30 → 0.124.32
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/actions/index.js +45 -0
- package/dist/api/read-client.js +105 -0
- package/dist/codegen/docs-cli.js +6 -0
- package/dist/codegen/docs.js +115 -0
- package/dist/codegen/generate-cli.js +17 -0
- package/dist/codegen/generate.js +214 -0
- package/dist/codegen/naming.js +164 -0
- package/dist/codegen/package.js +43 -0
- package/dist/composites/catalog.js +1245 -0
- package/dist/composites/cloud-function.js +65 -0
- package/dist/composites/cloud-run-service.js +71 -0
- package/dist/composites/cloud-sql-instance.js +85 -0
- package/dist/composites/gcs-bucket.js +64 -0
- package/dist/composites/gke-cluster.js +113 -0
- package/dist/composites/gke-crdb-region.js +137 -0
- package/dist/composites/gpu-node-pool.js +74 -0
- package/dist/composites/index.js +15 -0
- package/dist/composites/landing-zone.js +89 -0
- package/dist/composites/managed-certificate.js +46 -0
- package/dist/composites/memorystore-redis.js +52 -0
- package/dist/composites/multi-region-vpc.js +108 -0
- package/dist/composites/private-service.js +50 -0
- package/dist/composites/pubsub-pipeline.js +63 -0
- package/dist/composites/secure-project.js +85 -0
- package/dist/composites/vpc-network.js +113 -0
- package/dist/coverage.js +28 -0
- package/dist/deep-observe-hooks.js +152 -0
- package/dist/deep-observe.js +273 -0
- package/dist/default-labels.js +67 -0
- package/dist/describe-resources.js +264 -0
- package/dist/detect.js +16 -0
- package/dist/export-resources.js +59 -0
- package/dist/generated/index.js +1804 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/governance.js +98 -0
- package/dist/import/generator.js +68 -0
- package/dist/import/live-export.js +73 -0
- package/dist/import/parser.js +61 -0
- package/dist/index.js +36 -0
- package/dist/integrity.json +3 -3
- package/dist/lint/audit-catalog.js +38 -0
- package/dist/lint/audit-lineage.js +63 -0
- package/dist/lint/post-synth/gcp-helpers.js +91 -0
- package/dist/lint/post-synth/index.js +54 -0
- package/dist/lint/post-synth/schema-registry.d.ts.map +1 -1
- package/dist/lint/post-synth/schema-registry.js +69 -0
- package/dist/lint/post-synth/wgc101.js +47 -0
- package/dist/lint/post-synth/wgc102.js +29 -0
- package/dist/lint/post-synth/wgc103.js +37 -0
- package/dist/lint/post-synth/wgc104.js +34 -0
- package/dist/lint/post-synth/wgc105.js +39 -0
- package/dist/lint/post-synth/wgc106.js +30 -0
- package/dist/lint/post-synth/wgc107.js +33 -0
- package/dist/lint/post-synth/wgc108.js +34 -0
- package/dist/lint/post-synth/wgc109.js +33 -0
- package/dist/lint/post-synth/wgc110.js +32 -0
- package/dist/lint/post-synth/wgc111.js +47 -0
- package/dist/lint/post-synth/wgc112.js +46 -0
- package/dist/lint/post-synth/wgc113.js +35 -0
- package/dist/lint/post-synth/wgc201.js +30 -0
- package/dist/lint/post-synth/wgc202.js +33 -0
- package/dist/lint/post-synth/wgc203.js +35 -0
- package/dist/lint/post-synth/wgc204.js +33 -0
- package/dist/lint/post-synth/wgc301.js +28 -0
- package/dist/lint/post-synth/wgc302.js +28 -0
- package/dist/lint/post-synth/wgc303.js +29 -0
- package/dist/lint/post-synth/wgc401.js +50 -0
- package/dist/lint/post-synth/wgc402.js +46 -0
- package/dist/lint/post-synth/wgc403.js +74 -0
- package/dist/lint/post-synth/wgc501.js +63 -0
- package/dist/lint/post-synth/wgc502.js +37 -0
- package/dist/lint/post-synth/wgc503.js +49 -0
- package/dist/lint/rules/hardcoded-project.js +51 -0
- package/dist/lint/rules/hardcoded-region.js +51 -0
- package/dist/lint/rules/index.js +3 -0
- package/dist/lint/rules/public-iam.js +37 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +15 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +46 -0
- package/dist/manifest.json +1 -1
- package/dist/op/activities/floci-gcp.js +49 -0
- package/dist/op/activities/gcp-apply.js +618 -0
- package/dist/op/activities/index.js +10 -0
- package/dist/op/builders.js +50 -0
- package/dist/ownership.js +38 -0
- package/dist/package-cli.js +20 -0
- package/dist/plugin.js +371 -0
- package/dist/pseudo.js +15 -0
- package/dist/rules/schema-registry.ts +2 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +233 -0
- package/dist/spec/fetch.js +107 -0
- package/dist/spec/parse.js +323 -0
- package/dist/validate-cli.js +11 -0
- package/dist/validate.js +24 -0
- package/dist/variables.js +15 -0
- package/package.json +8 -8
- package/src/codegen/package.ts +2 -2
- package/src/lint/post-synth/schema-registry.ts +2 -1
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/serializer.ts +2 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builder wrappers for this lexicon's activities (chant #1288
|
|
3
|
+
* Stage 2). See `lexicons/k8s/src/op/builders.ts`'s module doc for why these
|
|
4
|
+
* live beside their `*Args` interfaces rather than in core: core cannot
|
|
5
|
+
* import a lexicon's types, so a wrapper whose `opts` IS the activity's own
|
|
6
|
+
* `*Args` interface can only sit in the lexicon that declares that
|
|
7
|
+
* interface. `opts`'s type in each wrapper below IS the activity's own
|
|
8
|
+
* `*Args` interface (via `Omit`/`WithStepRefs`) — never restated. `core`'s own
|
|
9
|
+
* `gcpApply`/`gcpDelete`/`flociGcpUp`/`flociGcpDown` are unchanged and
|
|
10
|
+
* produce byte-identical `ActivityStep` output; these are purely additive.
|
|
11
|
+
*/
|
|
12
|
+
import { activity, takeProfileAndId, } from "@intentius/chant/op";
|
|
13
|
+
/**
|
|
14
|
+
* Apply built GCP (CNRM) resources directly to their GCP REST APIs — the
|
|
15
|
+
* fully typed twin of core's `gcpApply`. `opts` is {@link GcpApplyArgs}
|
|
16
|
+
* itself, minus the positional `manifestPath`. Defaults to the `longInfra`
|
|
17
|
+
* profile.
|
|
18
|
+
*/
|
|
19
|
+
export const gcpApply = (manifestPath, opts) => {
|
|
20
|
+
const { args, profile, id } = takeProfileAndId(opts);
|
|
21
|
+
return activity("gcpApply", { manifestPath, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Delete the GCP (CNRM) resources in a built manifest — the inverse of
|
|
25
|
+
* {@link gcpApply}, fully typed twin of core's `gcpDelete`. `opts` is
|
|
26
|
+
* {@link GcpApplyArgs} itself (the activity reuses it), minus the positional
|
|
27
|
+
* `manifestPath`. Defaults to the `longInfra` profile.
|
|
28
|
+
*/
|
|
29
|
+
export const gcpDelete = (manifestPath, opts) => {
|
|
30
|
+
const { args, profile, id } = takeProfileAndId(opts);
|
|
31
|
+
return activity("gcpDelete", { manifestPath, ...args }, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Boot a local floci-gcp (GCP emulator) — the fully typed twin of core's
|
|
35
|
+
* `flociGcpUp`. `opts` is {@link FlociGcpUpArgs} itself. Defaults to the
|
|
36
|
+
* `longInfra` profile.
|
|
37
|
+
*/
|
|
38
|
+
export const flociGcpUp = (opts) => {
|
|
39
|
+
const { args, profile, id } = takeProfileAndId(opts);
|
|
40
|
+
return activity("flociGcpUp", args, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Stop and remove the local floci-gcp container — the fully typed twin of
|
|
44
|
+
* core's `flociGcpDown`. `opts` is {@link FlociGcpDownArgs} itself. Defaults
|
|
45
|
+
* to the `fastIdempotent` profile.
|
|
46
|
+
*/
|
|
47
|
+
export const flociGcpDown = (opts) => {
|
|
48
|
+
const { args, profile, id } = takeProfileAndId(opts);
|
|
49
|
+
return activity("flociGcpDown", args, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
|
|
50
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP's ownership marker channels (#1446).
|
|
3
|
+
*
|
|
4
|
+
* The gcp lexicon marks ownership on **two different surfaces**, and they
|
|
5
|
+
* legitimately use different key vocabularies:
|
|
6
|
+
*
|
|
7
|
+
* 1. **The Config Connector object** — what the serializer emits. Its
|
|
8
|
+
* `metadata.labels` are Kubernetes labels, so it uses core's shared
|
|
9
|
+
* `LABEL_OWNERSHIP_KEYS` (`app.kubernetes.io/managed-by`). That is the key
|
|
10
|
+
* `plugin.ts` registers as the lexicon's `ownershipChannel` and the one the
|
|
11
|
+
* read paths resolve through.
|
|
12
|
+
*
|
|
13
|
+
* 2. **The GCP resource itself** — what `gcpApply` PUTs to the REST API. GCP
|
|
14
|
+
* label keys may not contain `/` or `.`, so `app.kubernetes.io/managed-by`
|
|
15
|
+
* is not a legal key there. Hence {@link GCP_RESOURCE_OWNERSHIP_KEYS}.
|
|
16
|
+
*
|
|
17
|
+
* This is worth stating because the split looks like the bug #1446 found in the
|
|
18
|
+
* azure applier, and is not. Azure's serializer and applier both write ARM tags
|
|
19
|
+
* — one surface, and they had drifted onto two keys for no reason. Here the two
|
|
20
|
+
* surfaces are real and each key is the only legal one for its target.
|
|
21
|
+
*
|
|
22
|
+
* What #1446 changes is that the applier's predicate resolves through core's
|
|
23
|
+
* `hasOwnershipMarker` against a declared channel, rather than comparing a
|
|
24
|
+
* string literal inline. The key does not move; the drift risk does.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Ownership keys for labels on a live GCP resource — the surface `gcpApply`
|
|
28
|
+
* writes and `pruneOrphans` reads.
|
|
29
|
+
*
|
|
30
|
+
* GCP label keys are lowercase alphanumerics, `-` and `_` only, so this is the
|
|
31
|
+
* GCP-valid equivalent of core's label convention rather than that convention
|
|
32
|
+
* itself.
|
|
33
|
+
*/
|
|
34
|
+
export const GCP_RESOURCE_OWNERSHIP_KEYS = {
|
|
35
|
+
managedBy: "managed-by",
|
|
36
|
+
stack: "chant-stack",
|
|
37
|
+
env: "chant-env",
|
|
38
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Thin entry point for `npm run bundle` in lexicon-gcp.
|
|
4
|
+
* Generates src/generated/ files and writes dist/ bundle.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: Uses top-level await (matching AWS/Azure pattern) to avoid
|
|
7
|
+
* event loop references from async wrappers keeping the process alive.
|
|
8
|
+
*/
|
|
9
|
+
import { packageLexicon } from "./codegen/package.js";
|
|
10
|
+
import { writeBundleSpec } from "@intentius/chant/codegen/package";
|
|
11
|
+
import { dirname, join } from "path";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
const pkgDir = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const distDir = join(pkgDir, "..", "dist");
|
|
15
|
+
const verbose = process.argv.includes("--verbose") || !process.argv.includes("--quiet");
|
|
16
|
+
const force = process.argv.includes("--force");
|
|
17
|
+
const { spec, stats } = await packageLexicon({ verbose, force });
|
|
18
|
+
writeBundleSpec(spec, distDir);
|
|
19
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
20
|
+
console.error(`dist/ written to ${distDir}`);
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP Config Connector lexicon plugin.
|
|
3
|
+
*
|
|
4
|
+
* Provides serializer, lint rules, template detection,
|
|
5
|
+
* import parsing, and code generation for GCP Config Connector resources.
|
|
6
|
+
*/
|
|
7
|
+
import { compositeCatalog } from "./composites/catalog.js";
|
|
8
|
+
import { detectTemplate } from "./detect.js";
|
|
9
|
+
import { LABEL_OWNERSHIP_KEYS } from "@intentius/chant/ownership";
|
|
10
|
+
import { postSynthChecks as postSynthCheckList } from "./lint/post-synth/index.js";
|
|
11
|
+
import { gcpAuditCatalog } from "./lint/audit-catalog.js";
|
|
12
|
+
import { FLOCI_GCP_EMULATOR } from "./op/activities/floci-gcp.js";
|
|
13
|
+
import { createSkillsLoader, createDiffTool, createCatalogResource } from "@intentius/chant/lexicon-plugin-helpers";
|
|
14
|
+
import { gcpSerializer } from "./serializer.js";
|
|
15
|
+
import { hardcodedProjectRule } from "./lint/rules/hardcoded-project.js";
|
|
16
|
+
import { hardcodedRegionRule } from "./lint/rules/hardcoded-region.js";
|
|
17
|
+
import { publicIamRule } from "./lint/rules/public-iam.js";
|
|
18
|
+
import { GcpParser } from "./import/parser.js";
|
|
19
|
+
import { GcpGenerator } from "./import/generator.js";
|
|
20
|
+
import { gcpCompletions } from "./lsp/completions.js";
|
|
21
|
+
import { gcpHover } from "./lsp/hover.js";
|
|
22
|
+
import { gcpDeepNormalizationHooks } from "./deep-observe-hooks.js";
|
|
23
|
+
export const gcpPlugin = {
|
|
24
|
+
name: "gcp",
|
|
25
|
+
ownershipChannel: { keys: LABEL_OWNERSHIP_KEYS, reads: ["describeResources", "observeResourcesDeep", "exportResources"] },
|
|
26
|
+
emulator: FLOCI_GCP_EMULATOR,
|
|
27
|
+
auditCatalog: () => gcpAuditCatalog,
|
|
28
|
+
// Self-upgrade: where the pinned Config Connector (KCC) version lives + its upstream (#685).
|
|
29
|
+
upstreamPin: {
|
|
30
|
+
file: "src/spec/fetch.ts",
|
|
31
|
+
pattern: /export const KCC_VERSION\s*=\s*"([^"]+)"/,
|
|
32
|
+
replace: (v, line) => line.replace(/export const KCC_VERSION\s*=\s*"[^"]+"/, `export const KCC_VERSION = "${v}"`),
|
|
33
|
+
upstream: { owner: "GoogleCloudPlatform", repo: "k8s-config-connector", kind: "releases" },
|
|
34
|
+
},
|
|
35
|
+
serializer: gcpSerializer,
|
|
36
|
+
lintRules() {
|
|
37
|
+
return [hardcodedProjectRule, hardcodedRegionRule, publicIamRule];
|
|
38
|
+
},
|
|
39
|
+
postSynthChecks() {
|
|
40
|
+
return postSynthCheckList;
|
|
41
|
+
},
|
|
42
|
+
intrinsics() {
|
|
43
|
+
// Config Connector YAML has no intrinsic template functions
|
|
44
|
+
return [];
|
|
45
|
+
},
|
|
46
|
+
pseudoParameters() {
|
|
47
|
+
return [
|
|
48
|
+
"GCP::ProjectId",
|
|
49
|
+
"GCP::Region",
|
|
50
|
+
"GCP::Zone",
|
|
51
|
+
];
|
|
52
|
+
},
|
|
53
|
+
initTemplates(template) {
|
|
54
|
+
if (template === "gke") {
|
|
55
|
+
return {
|
|
56
|
+
src: {
|
|
57
|
+
"infra.ts": `/**
|
|
58
|
+
* GKE Cluster + Node Pool + Workload Identity
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
import { GKECluster, NodePool, GCPServiceAccount, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
|
|
62
|
+
import { defaultAnnotations } from "@intentius/chant-lexicon-gcp";
|
|
63
|
+
|
|
64
|
+
export const annotations = defaultAnnotations({
|
|
65
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const cluster = new GKECluster({
|
|
69
|
+
location: GCP.Region,
|
|
70
|
+
initialNodeCount: 1,
|
|
71
|
+
releaseChannel: { channel: "REGULAR" },
|
|
72
|
+
workloadIdentityConfig: {
|
|
73
|
+
workloadPool: \`\${GCP.ProjectId}.svc.id.goog\`,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export const nodePool = new NodePool({
|
|
78
|
+
clusterRef: { name: cluster },
|
|
79
|
+
initialNodeCount: 2,
|
|
80
|
+
autoscaling: { minNodeCount: 1, maxNodeCount: 10 },
|
|
81
|
+
nodeConfig: {
|
|
82
|
+
machineType: "e2-medium",
|
|
83
|
+
diskSizeGb: 100,
|
|
84
|
+
oauthScopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
85
|
+
workloadMetadataConfig: { mode: "GKE_METADATA" },
|
|
86
|
+
},
|
|
87
|
+
management: { autoRepair: true, autoUpgrade: true },
|
|
88
|
+
});
|
|
89
|
+
`,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (template === "cloud-function") {
|
|
94
|
+
return {
|
|
95
|
+
src: {
|
|
96
|
+
"infra.ts": `/**
|
|
97
|
+
* Cloud Function with Pub/Sub trigger
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
import { CloudFunction, StorageBucket, GCPServiceAccount, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
|
|
101
|
+
import { defaultAnnotations } from "@intentius/chant-lexicon-gcp";
|
|
102
|
+
|
|
103
|
+
export const annotations = defaultAnnotations({
|
|
104
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
export const sourceBucket = new StorageBucket({
|
|
108
|
+
location: GCP.Region,
|
|
109
|
+
storageClass: "STANDARD",
|
|
110
|
+
uniformBucketLevelAccess: true,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const functionSa = new GCPServiceAccount({
|
|
114
|
+
displayName: "Cloud Function Service Account",
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
export const fn = new CloudFunction({
|
|
118
|
+
location: GCP.Region,
|
|
119
|
+
runtime: "nodejs22",
|
|
120
|
+
entryPoint: "handler",
|
|
121
|
+
sourceArchiveBucket: sourceBucket,
|
|
122
|
+
sourceArchiveObject: "function-source.zip",
|
|
123
|
+
triggerHttp: true,
|
|
124
|
+
serviceAccountEmail: functionSa,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
export const invoker = new IAMPolicyMember({
|
|
128
|
+
member: "allUsers",
|
|
129
|
+
role: "roles/cloudfunctions.invoker",
|
|
130
|
+
resourceRef: {
|
|
131
|
+
apiVersion: "cloudfunctions.cnrm.cloud.google.com/v1beta1",
|
|
132
|
+
kind: "CloudFunction",
|
|
133
|
+
name: fn,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
`,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// Default: StorageBucket + IAMPolicyMember
|
|
141
|
+
return {
|
|
142
|
+
src: {
|
|
143
|
+
"infra.ts": `/**
|
|
144
|
+
* GCS Bucket with encryption and IAM binding
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
import { StorageBucket, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
|
|
148
|
+
import { defaultAnnotations } from "@intentius/chant-lexicon-gcp";
|
|
149
|
+
|
|
150
|
+
export const annotations = defaultAnnotations({
|
|
151
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
export const dataBucket = new StorageBucket({
|
|
155
|
+
location: "US",
|
|
156
|
+
storageClass: "STANDARD",
|
|
157
|
+
uniformBucketLevelAccess: true,
|
|
158
|
+
versioning: { enabled: true },
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
export const bucketReader = new IAMPolicyMember({
|
|
162
|
+
member: "serviceAccount:my-app@PROJECT_ID.iam.gserviceaccount.com",
|
|
163
|
+
role: "roles/storage.objectViewer",
|
|
164
|
+
resourceRef: {
|
|
165
|
+
apiVersion: "storage.cnrm.cloud.google.com/v1beta1",
|
|
166
|
+
kind: "StorageBucket",
|
|
167
|
+
name: dataBucket,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
`,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
detectTemplate,
|
|
175
|
+
templateParser() {
|
|
176
|
+
return new GcpParser();
|
|
177
|
+
},
|
|
178
|
+
templateGenerator() {
|
|
179
|
+
return new GcpGenerator();
|
|
180
|
+
},
|
|
181
|
+
completionProvider(ctx) {
|
|
182
|
+
return gcpCompletions(ctx);
|
|
183
|
+
},
|
|
184
|
+
hoverProvider(ctx) {
|
|
185
|
+
return gcpHover(ctx);
|
|
186
|
+
},
|
|
187
|
+
composites() {
|
|
188
|
+
return compositeCatalog;
|
|
189
|
+
},
|
|
190
|
+
mcpTools() {
|
|
191
|
+
return [createDiffTool(gcpSerializer, "Compare current build output against previous output for GCP Config Connector manifests", "gcp")];
|
|
192
|
+
},
|
|
193
|
+
mcpResources() {
|
|
194
|
+
return [
|
|
195
|
+
createCatalogResource(import.meta.url, "GCP Config Connector Resource Catalog", "JSON list of all supported GCP Config Connector resource types", "lexicon-gcp.json", "gcp"),
|
|
196
|
+
{
|
|
197
|
+
uri: "examples/basic-bucket",
|
|
198
|
+
name: "Basic GCS Bucket Example",
|
|
199
|
+
description: "A GCS bucket with encryption and IAM binding",
|
|
200
|
+
mimeType: "text/typescript",
|
|
201
|
+
async handler() {
|
|
202
|
+
return `import { StorageBucket, IAMPolicyMember, GCP } from "@intentius/chant-lexicon-gcp";
|
|
203
|
+
import { defaultAnnotations } from "@intentius/chant-lexicon-gcp";
|
|
204
|
+
|
|
205
|
+
export const annotations = defaultAnnotations({
|
|
206
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
export const bucket = new StorageBucket({
|
|
210
|
+
location: "US",
|
|
211
|
+
storageClass: "STANDARD",
|
|
212
|
+
uniformBucketLevelAccess: true,
|
|
213
|
+
versioning: { enabled: true },
|
|
214
|
+
});
|
|
215
|
+
`;
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
];
|
|
219
|
+
},
|
|
220
|
+
skills: createSkillsLoader(import.meta.url, [
|
|
221
|
+
{
|
|
222
|
+
file: "chant-gcp.md",
|
|
223
|
+
name: "chant-gcp",
|
|
224
|
+
description: "Build, validate, and deploy GCP Config Connector manifests from a chant project",
|
|
225
|
+
triggers: [
|
|
226
|
+
{ type: "file-pattern", value: "*.gcp.ts" },
|
|
227
|
+
{ type: "context", value: "gcp" },
|
|
228
|
+
],
|
|
229
|
+
parameters: [
|
|
230
|
+
{
|
|
231
|
+
name: "resourceType",
|
|
232
|
+
type: "string",
|
|
233
|
+
description: "GCP Config Connector resource type to work with",
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
examples: [
|
|
237
|
+
{
|
|
238
|
+
title: "Create a Storage Bucket",
|
|
239
|
+
output: "new StorageBucket({ location: \"US\", storageClass: \"STANDARD\" })",
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
title: "Create a GKE Cluster",
|
|
243
|
+
output: "new GKECluster({ location: GCP.Region, releaseChannel: { channel: \"REGULAR\" } })",
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
file: "chant-gcp-security.md",
|
|
249
|
+
name: "chant-gcp-security",
|
|
250
|
+
description: "GCP security best practices for infrastructure",
|
|
251
|
+
triggers: [
|
|
252
|
+
{ type: "context", value: "gcp security" },
|
|
253
|
+
{ type: "context", value: "gcp iam" },
|
|
254
|
+
],
|
|
255
|
+
parameters: [],
|
|
256
|
+
examples: [
|
|
257
|
+
{
|
|
258
|
+
title: "Secure Storage Bucket",
|
|
259
|
+
input: "Create a storage bucket with encryption and uniform access",
|
|
260
|
+
output: "import { GcsBucket } from \"@intentius/chant-lexicon-gcp\";\n\nconst { bucket } = GcsBucket({ name: \"my-bucket\", kmsKeyName: \"...\" });",
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
file: "chant-gcp-patterns.md",
|
|
266
|
+
name: "chant-gcp-patterns",
|
|
267
|
+
description: "Advanced GCP Config Connector patterns",
|
|
268
|
+
triggers: [
|
|
269
|
+
{ type: "context", value: "gcp patterns" },
|
|
270
|
+
{ type: "context", value: "gcp composites" },
|
|
271
|
+
],
|
|
272
|
+
parameters: [],
|
|
273
|
+
examples: [
|
|
274
|
+
{
|
|
275
|
+
title: "VPC with Subnets",
|
|
276
|
+
input: "Create a VPC network with private subnets",
|
|
277
|
+
output: "import { VpcNetwork } from \"@intentius/chant-lexicon-gcp\";\n\nconst { network, subnets } = VpcNetwork({ name: \"my-vpc\", subnets: [...] });",
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
file: "chant-gcp-gke.md",
|
|
283
|
+
name: "chant-gcp-gke",
|
|
284
|
+
description: "End-to-end GKE workflow bridging GCP infrastructure and Kubernetes workloads",
|
|
285
|
+
triggers: [
|
|
286
|
+
{ type: "context", value: "gke" },
|
|
287
|
+
{ type: "context", value: "gcp kubernetes" },
|
|
288
|
+
{ type: "context", value: "config connector" },
|
|
289
|
+
],
|
|
290
|
+
parameters: [],
|
|
291
|
+
examples: [
|
|
292
|
+
{
|
|
293
|
+
title: "Deploy GKE microservice",
|
|
294
|
+
input: "Deploy a GKE project end-to-end",
|
|
295
|
+
output: "npm run bootstrap && npm run deploy",
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
},
|
|
299
|
+
]),
|
|
300
|
+
async generate(options) {
|
|
301
|
+
const { generate, writeGeneratedFiles } = await import("./codegen/generate.js");
|
|
302
|
+
const { dirname } = await import("path");
|
|
303
|
+
const { fileURLToPath } = await import("url");
|
|
304
|
+
const result = await generate({ verbose: options?.verbose ?? true });
|
|
305
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
306
|
+
writeGeneratedFiles(result, pkgDir);
|
|
307
|
+
console.error(`Generated ${result.resources} resources, ${result.properties} property types, ${result.enums} enums`);
|
|
308
|
+
if (result.warnings.length > 0) {
|
|
309
|
+
console.error(`${result.warnings.length} warnings`);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
async validate(options) {
|
|
313
|
+
const { validate } = await import("./validate.js");
|
|
314
|
+
const { printValidationResult } = await import("@intentius/chant/codegen/validate");
|
|
315
|
+
const result = await validate();
|
|
316
|
+
printValidationResult(result);
|
|
317
|
+
},
|
|
318
|
+
async coverage(options) {
|
|
319
|
+
const { analyzeGcpCoverage } = await import("./coverage.js");
|
|
320
|
+
await analyzeGcpCoverage({
|
|
321
|
+
verbose: options?.verbose,
|
|
322
|
+
minOverall: options?.minOverall,
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
async package(options) {
|
|
326
|
+
const { packageLexicon } = await import("./codegen/package.js");
|
|
327
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
328
|
+
const { join, dirname } = await import("path");
|
|
329
|
+
const { fileURLToPath } = await import("url");
|
|
330
|
+
const { spec, stats } = await packageLexicon({ verbose: options?.verbose, force: options?.force });
|
|
331
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
332
|
+
const distDir = join(pkgDir, "dist");
|
|
333
|
+
writeBundleSpec(spec, distDir);
|
|
334
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
335
|
+
const { getRuntime } = await import("@intentius/chant/runtime-adapter");
|
|
336
|
+
const rt = getRuntime();
|
|
337
|
+
const { stdout: packOut, stderr: packErr, exitCode: packExit } = await rt.spawn(rt.commands.packCmd, { cwd: pkgDir });
|
|
338
|
+
if (packExit === 0) {
|
|
339
|
+
console.error(`Tarball: ${packOut.trim()}`);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
console.error(`${rt.commands.packCmd.join(" ")} failed: ${packErr}`);
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
async docs(options) {
|
|
346
|
+
const { generateDocs } = await import("./codegen/docs.js");
|
|
347
|
+
await generateDocs(options);
|
|
348
|
+
},
|
|
349
|
+
async describeResources(options) {
|
|
350
|
+
const { describeResources } = await import("./describe-resources.js");
|
|
351
|
+
return describeResources(options);
|
|
352
|
+
},
|
|
353
|
+
async exportResources(options) {
|
|
354
|
+
const { exportResources } = await import("./export-resources.js");
|
|
355
|
+
return exportResources(options);
|
|
356
|
+
},
|
|
357
|
+
// Property-level live drift via SSA managed-fields (#1087, epic #1073),
|
|
358
|
+
// reusing the k8s row (#1076) rather than writing a second implementation —
|
|
359
|
+
// a Config Connector custom resource is a Kubernetes object too. The
|
|
360
|
+
// reader lives in ./deep-observe.ts, loaded only through this dynamic
|
|
361
|
+
// import — same reason describeResources/exportResources are — so nothing
|
|
362
|
+
// on the build path resolves the live kubectl transport it shares with
|
|
363
|
+
// ./describe-resources.ts. deepNormalizationHooks is plain data with no
|
|
364
|
+
// transport dependency and is imported statically above, because core
|
|
365
|
+
// applies it to the *declared* tree whether or not a live read ever happens.
|
|
366
|
+
async observeResourcesDeep(options) {
|
|
367
|
+
const { observeResourcesDeepGcp } = await import("./deep-observe.js");
|
|
368
|
+
return observeResourcesDeepGcp(options);
|
|
369
|
+
},
|
|
370
|
+
deepNormalizationHooks: gcpDeepNormalizationHooks,
|
|
371
|
+
};
|
package/dist/pseudo.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PseudoParameter, createPseudoParameters } from "@intentius/chant/pseudo-parameter";
|
|
2
|
+
export { PseudoParameter };
|
|
3
|
+
export const { ProjectId, Region, Zone } = createPseudoParameters({
|
|
4
|
+
ProjectId: "GCP::ProjectId",
|
|
5
|
+
Region: "GCP::Region",
|
|
6
|
+
Zone: "GCP::Zone",
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* GCP namespace containing all pseudo-parameters.
|
|
10
|
+
*/
|
|
11
|
+
export const GCP = {
|
|
12
|
+
ProjectId,
|
|
13
|
+
Region,
|
|
14
|
+
Zone,
|
|
15
|
+
};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { createRequire } from "module";
|
|
9
|
+
import { moduleSourceUrl } from "@intentius/chant/module-source";
|
|
9
10
|
|
|
10
11
|
export interface FieldSchema {
|
|
11
12
|
type: string;
|
|
@@ -38,7 +39,7 @@ export function getSchemaRegistry(): Map<string, ResourceSchema> {
|
|
|
38
39
|
// Built lazily (not at module load) so importing this module stays edge-safe:
|
|
39
40
|
// `createRequire(import.meta.url)` throws where import.meta.url is undefined
|
|
40
41
|
// (bundled Workers); there it's caught here and the registry is just empty.
|
|
41
|
-
const require = createRequire(import.meta.url);
|
|
42
|
+
const require = createRequire(moduleSourceUrl(import.meta.url));
|
|
42
43
|
const lexicon = require("../../generated/lexicon-gcp.json") as Record<string, LexiconEntry>;
|
|
43
44
|
for (const entry of Object.values(lexicon)) {
|
|
44
45
|
if (entry.kind === "resource" && entry.gvkKind && entry.schema) {
|
package/dist/serializer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAsC,MAAM,6BAA6B,CAAC;AAiClG;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAW1F;AAuDD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,UA2F3B,CAAC"}
|