@intentius/chant-lexicon-gcp 0.124.33 → 0.124.34
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/deep-observe.js +1 -1
- package/dist/describe-resources.d.ts +4 -3
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/describe-resources.js +8 -7
- package/dist/health.js +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/op/activities/gcp-apply.d.ts +7 -0
- package/dist/op/activities/gcp-apply.d.ts.map +1 -1
- package/dist/op/activities/gcp-apply.js +25 -2
- package/dist/op/activities/index.d.ts +1 -1
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +1 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +36 -1
- package/package.json +2 -2
- package/src/deep-observe.ts +1 -1
- package/src/describe-resources.ts +8 -6
- package/src/health.ts +1 -1
- package/src/op/activities/gcp-apply.test.ts +16 -0
- package/src/op/activities/gcp-apply.ts +25 -2
- package/src/op/activities/index.ts +1 -0
- package/src/project-resolution.test.ts +41 -0
- package/src/serializer-pseudo.test.ts +38 -0
- package/src/serializer.ts +43 -3
package/dist/deep-observe.js
CHANGED
|
@@ -213,7 +213,7 @@ export async function observeResourcesDeepGcp(options) {
|
|
|
213
213
|
let client;
|
|
214
214
|
try {
|
|
215
215
|
client = {
|
|
216
|
-
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects),
|
|
216
|
+
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects, props),
|
|
217
217
|
...(endpoint ? { endpoint } : {}),
|
|
218
218
|
};
|
|
219
219
|
}
|
|
@@ -82,14 +82,15 @@ export declare function deriveGVK(entityType: string): {
|
|
|
82
82
|
*/
|
|
83
83
|
export declare function manifestProjectAnnotations(buildOutput: string | undefined): Map<string, string>;
|
|
84
84
|
/**
|
|
85
|
-
* The project a read should target:
|
|
86
|
-
*
|
|
85
|
+
* The project a read should target: the entity's `projectRef.external`,
|
|
86
|
+
* `GOOGLE_CLOUD_PROJECT`, the entity's own annotation (via
|
|
87
|
+
* `resolveGcpProject`, the applier's rule), then the built
|
|
87
88
|
* manifest's merged annotation. Throws the applier's own error when nothing
|
|
88
89
|
* resolves, so the `no-binding` detail names both knobs.
|
|
89
90
|
*/
|
|
90
91
|
export declare function resolveReadProject(kind: string, name: string, metadata: {
|
|
91
92
|
annotations?: Record<string, string>;
|
|
92
|
-
} | undefined, manifestProjects: Map<string, string>): string;
|
|
93
|
+
} | undefined, manifestProjects: Map<string, string>, props?: Record<string, unknown>): string;
|
|
93
94
|
/**
|
|
94
95
|
* Status from a REST payload.
|
|
95
96
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe-resources.d.ts","sourceRoot":"","sources":["../src/describe-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAsC,MAAM,0BAA0B,CAAC;AAsBtG;;gCAEgC;AAChC,UAAU,eAAe;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACxF,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;KACtB,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAIpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAgB/F;AAED
|
|
1
|
+
{"version":3,"file":"describe-resources.d.ts","sourceRoot":"","sources":["../src/describe-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAsC,MAAM,0BAA0B,CAAC;AAsBtG;;gCAEgC;AAChC,UAAU,eAAe;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACxF,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;KACtB,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAIpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAgB/F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,SAAS,EAC9D,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAQR;AAUD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAY3D;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwH7B"}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
import { observation } from "@intentius/chant/observation";
|
|
39
39
|
import { hasOwnershipMarker, classifyOwnership, readOwnership } from "@intentius/chant/ownership";
|
|
40
40
|
import { getResource, mapperForKind, GcpReadError, isNotFound } from "./api/read-client.js";
|
|
41
|
-
import { resolveGcpProject, parseManifest } from "./op/activities/gcp-apply.js";
|
|
41
|
+
import { resolveGcpProject, parseManifest, projectRefProject } from "./op/activities/gcp-apply.js";
|
|
42
42
|
import { resolveGVK } from "./serializer.js";
|
|
43
43
|
/**
|
|
44
44
|
* chant's ownership marker as GCP labels.
|
|
@@ -85,7 +85,7 @@ export function manifestProjectAnnotations(buildOutput) {
|
|
|
85
85
|
return out;
|
|
86
86
|
try {
|
|
87
87
|
for (const doc of parseManifest(buildOutput, "<build output>")) {
|
|
88
|
-
const project = doc.metadata?.annotations?.["cnrm.cloud.google.com/project-id"];
|
|
88
|
+
const project = projectRefProject(doc.spec) ?? doc.metadata?.annotations?.["cnrm.cloud.google.com/project-id"];
|
|
89
89
|
if (doc.kind && doc.metadata?.name && typeof project === "string") {
|
|
90
90
|
out.set(`${doc.kind}/${doc.metadata.name}`, project);
|
|
91
91
|
}
|
|
@@ -99,14 +99,15 @@ export function manifestProjectAnnotations(buildOutput) {
|
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
102
|
-
* The project a read should target:
|
|
103
|
-
*
|
|
102
|
+
* The project a read should target: the entity's `projectRef.external`,
|
|
103
|
+
* `GOOGLE_CLOUD_PROJECT`, the entity's own annotation (via
|
|
104
|
+
* `resolveGcpProject`, the applier's rule), then the built
|
|
104
105
|
* manifest's merged annotation. Throws the applier's own error when nothing
|
|
105
106
|
* resolves, so the `no-binding` detail names both knobs.
|
|
106
107
|
*/
|
|
107
|
-
export function resolveReadProject(kind, name, metadata, manifestProjects) {
|
|
108
|
+
export function resolveReadProject(kind, name, metadata, manifestProjects, props) {
|
|
108
109
|
try {
|
|
109
|
-
return resolveGcpProject({ kind, metadata });
|
|
110
|
+
return resolveGcpProject({ kind, metadata, ...(props ? { spec: props } : {}) });
|
|
110
111
|
}
|
|
111
112
|
catch (err) {
|
|
112
113
|
const fromManifest = manifestProjects.get(`${kind}/${name}`);
|
|
@@ -195,7 +196,7 @@ export async function describeResources(options) {
|
|
|
195
196
|
let client;
|
|
196
197
|
try {
|
|
197
198
|
client = {
|
|
198
|
-
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects),
|
|
199
|
+
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects, props),
|
|
199
200
|
...(endpoint ? { endpoint } : {}),
|
|
200
201
|
};
|
|
201
202
|
}
|
package/dist/health.js
CHANGED
|
@@ -60,7 +60,7 @@ export async function observeHealthGcp(options) {
|
|
|
60
60
|
}
|
|
61
61
|
let project;
|
|
62
62
|
try {
|
|
63
|
-
project = resolveReadProject(gvk.kind, name, metadata, manifestProjects);
|
|
63
|
+
project = resolveReadProject(gvk.kind, name, metadata, manifestProjects, props);
|
|
64
64
|
}
|
|
65
65
|
catch (err) {
|
|
66
66
|
unobserved[entityName] = { type: entityType, reason: "no-binding", detail: err instanceof Error ? err.message : String(err) };
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "98144aa547c946b5a9d5053dda7d27486e5d86a646bc19debf696af5aed118b1",
|
|
5
5
|
"meta.json": "75643660010c044c6f465bef2688a864ab30cc96fd9b68111969749748ac64ca",
|
|
6
6
|
"types/index.d.ts": "da1ebc6bcf83e1a018a773b59714194aeeb74ae1d5c1252b737b7e730ca98bd5",
|
|
7
7
|
"rules/hardcoded-project.ts": "6d5ae9efa74d73800eebe1a0a0d43c619ee0fdebe3347195df93fcbe63b34f0d",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"skills/chant-gcp-patterns.md": "4c6809fc7c37fa1879379ad4c0e2d114dec9497bc6eb9d1bca4e79fddea4f509",
|
|
41
41
|
"skills/chant-gcp-gke.md": "be277019da9a722c851e47cd2dfb9c9536668948c3535fb20db7697e934c4e2b"
|
|
42
42
|
},
|
|
43
|
-
"composite": "
|
|
43
|
+
"composite": "42adf7f5bc414f125aa92b289f431803d8c659a76e1d3ba8ad393da238c2ac53"
|
|
44
44
|
}
|
package/dist/manifest.json
CHANGED
|
@@ -197,6 +197,13 @@ export declare function resolveGcpEndpoint(args?: {
|
|
|
197
197
|
endpoint?: string;
|
|
198
198
|
}, env?: NodeJS.ProcessEnv): string | undefined;
|
|
199
199
|
/** Resolve the project: `GOOGLE_CLOUD_PROJECT` env, else the CNRM project-id annotation. Pure. */
|
|
200
|
+
/**
|
|
201
|
+
* The project a resource names in `spec.projectRef.external` (#4201): a
|
|
202
|
+
* project id or `projects/<id>`. A `GCP.ProjectId` pseudo-parameter there
|
|
203
|
+
* (`{ Ref: "GCP::ProjectId" }`, unresolved in discovery output) reads
|
|
204
|
+
* `GCP_PROJECT_ID`, as the serializer does.
|
|
205
|
+
*/
|
|
206
|
+
export declare function projectRefProject(spec: Record<string, unknown> | undefined, env?: NodeJS.ProcessEnv): string | undefined;
|
|
200
207
|
export declare function resolveGcpProject(resource: GcpResource, env?: NodeJS.ProcessEnv): string;
|
|
201
208
|
/** Injectable HTTP client — mirrors argo's injectable fetcher so tests avoid the network. */
|
|
202
209
|
export type GcpHttp = (method: string, url: string, body?: unknown, signal?: AbortSignal) => Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gcp-apply.d.ts","sourceRoot":"","sources":["../../../src/op/activities/gcp-apply.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"gcp-apply.d.ts","sourceRoot":"","sources":["../../../src/op/activities/gcp-apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -333,10 +333,33 @@ export function resolveGcpEndpoint(args = {}, env = process.env) {
|
|
|
333
333
|
return args.endpoint || env.GCP_ENDPOINT_URL || undefined;
|
|
334
334
|
}
|
|
335
335
|
/** Resolve the project: `GOOGLE_CLOUD_PROJECT` env, else the CNRM project-id annotation. Pure. */
|
|
336
|
+
/**
|
|
337
|
+
* The project a resource names in `spec.projectRef.external` (#4201): a
|
|
338
|
+
* project id or `projects/<id>`. A `GCP.ProjectId` pseudo-parameter there
|
|
339
|
+
* (`{ Ref: "GCP::ProjectId" }`, unresolved in discovery output) reads
|
|
340
|
+
* `GCP_PROJECT_ID`, as the serializer does.
|
|
341
|
+
*/
|
|
342
|
+
export function projectRefProject(spec, env = process.env) {
|
|
343
|
+
const ref = spec?.projectRef;
|
|
344
|
+
if (ref === null || typeof ref !== "object")
|
|
345
|
+
return undefined;
|
|
346
|
+
let external = ref.external;
|
|
347
|
+
if (external !== null && typeof external === "object" && typeof external.toJSON === "function") {
|
|
348
|
+
external = external.toJSON();
|
|
349
|
+
}
|
|
350
|
+
if (external !== null && typeof external === "object" && external.Ref === "GCP::ProjectId") {
|
|
351
|
+
return env.GCP_PROJECT_ID || undefined;
|
|
352
|
+
}
|
|
353
|
+
if (typeof external !== "string" || external === "")
|
|
354
|
+
return undefined;
|
|
355
|
+
return external.startsWith("projects/") ? external.slice("projects/".length).split("/")[0] : external;
|
|
356
|
+
}
|
|
336
357
|
export function resolveGcpProject(resource, env = process.env) {
|
|
337
|
-
const project =
|
|
358
|
+
const project = projectRefProject(resource.spec, env) ||
|
|
359
|
+
env.GOOGLE_CLOUD_PROJECT ||
|
|
360
|
+
resource.metadata?.annotations?.[PROJECT_ID_ANNOTATION];
|
|
338
361
|
if (!project) {
|
|
339
|
-
throw new Error(`no GCP project — set GOOGLE_CLOUD_PROJECT or the ${PROJECT_ID_ANNOTATION} annotation`);
|
|
362
|
+
throw new Error(`no GCP project — set spec.projectRef.external, GOOGLE_CLOUD_PROJECT or the ${PROJECT_ID_ANNOTATION} annotation`);
|
|
340
363
|
}
|
|
341
364
|
return project;
|
|
342
365
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (`gcpApply`), which maps CNRM resources to GCP REST calls since GCP has no
|
|
5
5
|
* native deployment service to shell out to.
|
|
6
6
|
*/
|
|
7
|
-
export { gcpApply, gcpDelete, applyResource, deleteResource, waitForOperation, longRunningOperation, bucketInsertBody, pubSubTopicBody, pubSubSubscriptionBody, cloudRunServiceBody, secretBody, serviceAccountBody, storageBucketMapper, pubSubTopicMapper, pubSubSubscriptionMapper, cloudRunServiceMapper, secretManagerSecretMapper, gcpServiceAccountMapper, MAPPERS, referencedNames, orderByReferences, pruneOrphans, toApplyResult, type GcpNotAttempted, type GcpNotPrunable, chantOwnershipLabels, isChantOwned, resolveGcpEndpoint, resolveGcpProject, parseManifest, } from "./gcp-apply.js";
|
|
7
|
+
export { gcpApply, gcpDelete, applyResource, deleteResource, waitForOperation, longRunningOperation, bucketInsertBody, pubSubTopicBody, pubSubSubscriptionBody, cloudRunServiceBody, secretBody, serviceAccountBody, storageBucketMapper, pubSubTopicMapper, pubSubSubscriptionMapper, cloudRunServiceMapper, secretManagerSecretMapper, gcpServiceAccountMapper, MAPPERS, referencedNames, orderByReferences, pruneOrphans, toApplyResult, type GcpNotAttempted, type GcpNotPrunable, chantOwnershipLabels, isChantOwned, resolveGcpEndpoint, resolveGcpProject, projectRefProject, parseManifest, } from "./gcp-apply.js";
|
|
8
8
|
export type { GcpApplyArgs, GcpResource, CnrmStorageBucket, BucketInsertBody, PubSubTopicBody, ResourceMapper, OperationSpec, ListSpec, ApplyPlan, GcpHttp, } from "./gcp-apply.js";
|
|
9
9
|
export { flociGcpUp, flociGcpDown, flociGcpRunCommand, flociGcpRmCommand, flociGcpExistsCommand, flociGcpHealthUrl, flociGcpEndpoint, } from "./floci-gcp.js";
|
|
10
10
|
export type { FlociGcpUpArgs, FlociGcpDownArgs } from "./floci-gcp.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,EACvB,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,aAAa,EACb,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,EACvB,OAAO,EACP,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,aAAa,EACb,QAAQ,EACR,SAAS,EACT,OAAO,GACR,MAAM,aAAa,CAAC;AAIrB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (`gcpApply`), which maps CNRM resources to GCP REST calls since GCP has no
|
|
5
5
|
* native deployment service to shell out to.
|
|
6
6
|
*/
|
|
7
|
-
export { gcpApply, gcpDelete, applyResource, deleteResource, waitForOperation, longRunningOperation, bucketInsertBody, pubSubTopicBody, pubSubSubscriptionBody, cloudRunServiceBody, secretBody, serviceAccountBody, storageBucketMapper, pubSubTopicMapper, pubSubSubscriptionMapper, cloudRunServiceMapper, secretManagerSecretMapper, gcpServiceAccountMapper, MAPPERS, referencedNames, orderByReferences, pruneOrphans, toApplyResult, chantOwnershipLabels, isChantOwned, resolveGcpEndpoint, resolveGcpProject, parseManifest, } from "./gcp-apply.js";
|
|
7
|
+
export { gcpApply, gcpDelete, applyResource, deleteResource, waitForOperation, longRunningOperation, bucketInsertBody, pubSubTopicBody, pubSubSubscriptionBody, cloudRunServiceBody, secretBody, serviceAccountBody, storageBucketMapper, pubSubTopicMapper, pubSubSubscriptionMapper, cloudRunServiceMapper, secretManagerSecretMapper, gcpServiceAccountMapper, MAPPERS, referencedNames, orderByReferences, pruneOrphans, toApplyResult, chantOwnershipLabels, isChantOwned, resolveGcpEndpoint, resolveGcpProject, projectRefProject, parseManifest, } from "./gcp-apply.js";
|
|
8
8
|
// floci-gcp (GCP emulator) lifecycle — the typed twin of aws's flociUp/Down, so
|
|
9
9
|
// the trio's GCP op boots/tears down the emulator as a modeled step, not a shell.
|
|
10
10
|
export { flociGcpUp, flociGcpDown, flociGcpRunCommand, flociGcpRmCommand, flociGcpExistsCommand, flociGcpHealthUrl, flociGcpEndpoint, } from "./floci-gcp.js";
|
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;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;AAsED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,
|
|
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;AAsED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,UAiG3B,CAAC"}
|
package/dist/serializer.js
CHANGED
|
@@ -131,6 +131,7 @@ export const gcpSerializer = {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
const documents = [];
|
|
134
|
+
const unresolved = [];
|
|
134
135
|
for (const [name, entity] of entities) {
|
|
135
136
|
if (isPropertyDeclarable(entity))
|
|
136
137
|
continue;
|
|
@@ -140,7 +141,7 @@ export const gcpSerializer = {
|
|
|
140
141
|
const gvk = resolveGVK(entityType);
|
|
141
142
|
if (!gvk)
|
|
142
143
|
continue;
|
|
143
|
-
const props = toYAMLValue(isResourceDeclarable(entity) ? entity.props : undefined, entityNames);
|
|
144
|
+
const props = resolvePseudoParameters(toYAMLValue(isResourceDeclarable(entity) ? entity.props : undefined, entityNames), name, unresolved);
|
|
144
145
|
if (!props)
|
|
145
146
|
continue;
|
|
146
147
|
// Build the Config Connector manifest structure
|
|
@@ -181,6 +182,8 @@ export const gcpSerializer = {
|
|
|
181
182
|
const yamlDoc = emitK8sManifest(manifest);
|
|
182
183
|
documents.push(yamlDoc);
|
|
183
184
|
}
|
|
185
|
+
if (unresolved.length > 0)
|
|
186
|
+
throw new Error(unresolvedMessage(unresolved));
|
|
184
187
|
const primary = documents.join("\n---\n");
|
|
185
188
|
const warnings = unwritableOutputWarnings(outputs);
|
|
186
189
|
return warnings.length > 0 ? { primary, warnings } : primary;
|
|
@@ -196,6 +199,38 @@ const PSEUDO_ENV_MAP = {
|
|
|
196
199
|
"GCP::Region": { envVar: "GCP_REGION", fallback: "us-central1" },
|
|
197
200
|
"GCP::Zone": { envVar: "GCP_ZONE", fallback: "us-central1-a" },
|
|
198
201
|
};
|
|
202
|
+
/**
|
|
203
|
+
* Replace each GCP pseudo-parameter (`{ Ref: "GCP::Region" }`) in a
|
|
204
|
+
* serialized resource with its environment variable's value (#4200).
|
|
205
|
+
* Config Connector has no parameters, so a `Ref` left in the YAML reaches
|
|
206
|
+
* the API as an object. A variable that isn't set is recorded, and the
|
|
207
|
+
* build refuses with every one named.
|
|
208
|
+
*/
|
|
209
|
+
function resolvePseudoParameters(value, entity, unresolved) {
|
|
210
|
+
if (Array.isArray(value))
|
|
211
|
+
return value.map((v) => resolvePseudoParameters(v, entity, unresolved));
|
|
212
|
+
if (value === null || typeof value !== "object")
|
|
213
|
+
return value;
|
|
214
|
+
const obj = value;
|
|
215
|
+
const keys = Object.keys(obj);
|
|
216
|
+
if (keys.length === 1 && keys[0] === "Ref" && typeof obj.Ref === "string" && obj.Ref in PSEUDO_ENV_MAP) {
|
|
217
|
+
const { envVar } = PSEUDO_ENV_MAP[obj.Ref];
|
|
218
|
+
const resolved = process.env[envVar];
|
|
219
|
+
if (resolved)
|
|
220
|
+
return resolved;
|
|
221
|
+
unresolved.push({ entity, ref: obj.Ref, envVar });
|
|
222
|
+
return value;
|
|
223
|
+
}
|
|
224
|
+
const out = {};
|
|
225
|
+
for (const [k, v] of Object.entries(obj))
|
|
226
|
+
out[k] = resolvePseudoParameters(v, entity, unresolved);
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
function unresolvedMessage(unresolved) {
|
|
230
|
+
const vars = [...new Set(unresolved.map((u) => u.envVar))];
|
|
231
|
+
const lines = unresolved.map((u) => ` ${u.entity}: ${u.ref} needs ${u.envVar}`);
|
|
232
|
+
return `gcp: ${vars.join(", ")} ${vars.length === 1 ? "is" : "are"} not set, and Config Connector YAML can't carry a pseudo-parameter. Set ${vars.length === 1 ? "it" : "them"} at build, or pass the value explicitly:\n${lines.join("\n")}`;
|
|
233
|
+
}
|
|
199
234
|
/**
|
|
200
235
|
* Resolve an annotation value to a plain string.
|
|
201
236
|
* PseudoParameter intrinsics are resolved from environment variables;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-gcp",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.34",
|
|
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,6 +76,6 @@
|
|
|
76
76
|
"typescript": "^5.9.3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
|
-
"@intentius/chant": "^0.124.
|
|
79
|
+
"@intentius/chant": "^0.124.34"
|
|
80
80
|
}
|
|
81
81
|
}
|
package/src/deep-observe.ts
CHANGED
|
@@ -244,7 +244,7 @@ export async function observeResourcesDeepGcp(options: GcpDeepObserveOptions): P
|
|
|
244
244
|
let client: GcpReadClientOptions;
|
|
245
245
|
try {
|
|
246
246
|
client = {
|
|
247
|
-
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects),
|
|
247
|
+
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects, props),
|
|
248
248
|
...(endpoint ? { endpoint } : {}),
|
|
249
249
|
};
|
|
250
250
|
} catch (err) {
|
|
@@ -40,7 +40,7 @@ import type { ObservationResult, ResourceMetadata, UnobservedEntity } from "@int
|
|
|
40
40
|
import { observation } from "@intentius/chant/observation";
|
|
41
41
|
import { hasOwnershipMarker, classifyOwnership, readOwnership, type ChannelKeys } from "@intentius/chant/ownership";
|
|
42
42
|
import { getResource, mapperForKind, GcpReadError, isNotFound, type GcpReadClientOptions } from "./api/read-client";
|
|
43
|
-
import { resolveGcpProject, parseManifest } from "./op/activities/gcp-apply";
|
|
43
|
+
import { resolveGcpProject, parseManifest, projectRefProject } from "./op/activities/gcp-apply";
|
|
44
44
|
import { resolveGVK } from "./serializer";
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -105,7 +105,7 @@ export function manifestProjectAnnotations(buildOutput: string | undefined): Map
|
|
|
105
105
|
if (!buildOutput) return out;
|
|
106
106
|
try {
|
|
107
107
|
for (const doc of parseManifest(buildOutput, "<build output>")) {
|
|
108
|
-
const project = doc.metadata?.annotations?.["cnrm.cloud.google.com/project-id"];
|
|
108
|
+
const project = projectRefProject(doc.spec) ?? doc.metadata?.annotations?.["cnrm.cloud.google.com/project-id"];
|
|
109
109
|
if (doc.kind && doc.metadata?.name && typeof project === "string") {
|
|
110
110
|
out.set(`${doc.kind}/${doc.metadata.name}`, project);
|
|
111
111
|
}
|
|
@@ -119,8 +119,9 @@ export function manifestProjectAnnotations(buildOutput: string | undefined): Map
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
|
-
* The project a read should target:
|
|
123
|
-
*
|
|
122
|
+
* The project a read should target: the entity's `projectRef.external`,
|
|
123
|
+
* `GOOGLE_CLOUD_PROJECT`, the entity's own annotation (via
|
|
124
|
+
* `resolveGcpProject`, the applier's rule), then the built
|
|
124
125
|
* manifest's merged annotation. Throws the applier's own error when nothing
|
|
125
126
|
* resolves, so the `no-binding` detail names both knobs.
|
|
126
127
|
*/
|
|
@@ -129,9 +130,10 @@ export function resolveReadProject(
|
|
|
129
130
|
name: string,
|
|
130
131
|
metadata: { annotations?: Record<string, string> } | undefined,
|
|
131
132
|
manifestProjects: Map<string, string>,
|
|
133
|
+
props?: Record<string, unknown>,
|
|
132
134
|
): string {
|
|
133
135
|
try {
|
|
134
|
-
return resolveGcpProject({ kind, metadata });
|
|
136
|
+
return resolveGcpProject({ kind, metadata, ...(props ? { spec: props } : {}) });
|
|
135
137
|
} catch (err) {
|
|
136
138
|
const fromManifest = manifestProjects.get(`${kind}/${name}`);
|
|
137
139
|
if (fromManifest) return fromManifest;
|
|
@@ -230,7 +232,7 @@ export async function describeResources(options: {
|
|
|
230
232
|
let client: GcpReadClientOptions;
|
|
231
233
|
try {
|
|
232
234
|
client = {
|
|
233
|
-
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects),
|
|
235
|
+
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects, props),
|
|
234
236
|
...(endpoint ? { endpoint } : {}),
|
|
235
237
|
};
|
|
236
238
|
} catch (err) {
|
package/src/health.ts
CHANGED
|
@@ -91,7 +91,7 @@ export async function observeHealthGcp(options: GcpHealthOptions): Promise<Healt
|
|
|
91
91
|
}
|
|
92
92
|
let project: string;
|
|
93
93
|
try {
|
|
94
|
-
project = resolveReadProject(gvk.kind, name, metadata, manifestProjects);
|
|
94
|
+
project = resolveReadProject(gvk.kind, name, metadata, manifestProjects, props);
|
|
95
95
|
} catch (err) {
|
|
96
96
|
unobserved[entityName] = { type: entityType, reason: "no-binding", detail: err instanceof Error ? err.message : String(err) };
|
|
97
97
|
return;
|
|
@@ -234,6 +234,22 @@ describe("resolveGcpProject (#711)", () => {
|
|
|
234
234
|
expect(() => resolveGcpProject({ metadata: { name: "b" } }, {} as NodeJS.ProcessEnv))
|
|
235
235
|
.toThrow(/no GCP project/);
|
|
236
236
|
});
|
|
237
|
+
|
|
238
|
+
test("spec.projectRef.external wins over env and the annotation (#4201)", () => {
|
|
239
|
+
const run = { ...BUCKET, spec: { projectRef: { external: "ref-project" } } };
|
|
240
|
+
expect(resolveGcpProject(run, { GOOGLE_CLOUD_PROJECT: "env-project" } as NodeJS.ProcessEnv)).toBe("ref-project");
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test("projectRef.external may be projects/<id>", () => {
|
|
244
|
+
const run = { metadata: { name: "r" }, spec: { projectRef: { external: "projects/three-cloud" } } };
|
|
245
|
+
expect(resolveGcpProject(run, {} as NodeJS.ProcessEnv)).toBe("three-cloud");
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test("an unresolved GCP.ProjectId in projectRef reads GCP_PROJECT_ID, else falls through", () => {
|
|
249
|
+
const run = { ...BUCKET, spec: { projectRef: { external: { Ref: "GCP::ProjectId" } } } };
|
|
250
|
+
expect(resolveGcpProject(run, { GCP_PROJECT_ID: "pseudo-project" } as NodeJS.ProcessEnv)).toBe("pseudo-project");
|
|
251
|
+
expect(resolveGcpProject(run, {} as NodeJS.ProcessEnv)).toBe("annotated-project");
|
|
252
|
+
});
|
|
237
253
|
});
|
|
238
254
|
|
|
239
255
|
describe("resolveGcpEndpoint (#1449)", () => {
|
|
@@ -443,11 +443,34 @@ export function resolveGcpEndpoint(
|
|
|
443
443
|
}
|
|
444
444
|
|
|
445
445
|
/** Resolve the project: `GOOGLE_CLOUD_PROJECT` env, else the CNRM project-id annotation. Pure. */
|
|
446
|
+
/**
|
|
447
|
+
* The project a resource names in `spec.projectRef.external` (#4201): a
|
|
448
|
+
* project id or `projects/<id>`. A `GCP.ProjectId` pseudo-parameter there
|
|
449
|
+
* (`{ Ref: "GCP::ProjectId" }`, unresolved in discovery output) reads
|
|
450
|
+
* `GCP_PROJECT_ID`, as the serializer does.
|
|
451
|
+
*/
|
|
452
|
+
export function projectRefProject(spec: Record<string, unknown> | undefined, env: NodeJS.ProcessEnv = process.env): string | undefined {
|
|
453
|
+
const ref = spec?.projectRef;
|
|
454
|
+
if (ref === null || typeof ref !== "object") return undefined;
|
|
455
|
+
let external = (ref as Record<string, unknown>).external;
|
|
456
|
+
if (external !== null && typeof external === "object" && typeof (external as { toJSON?: unknown }).toJSON === "function") {
|
|
457
|
+
external = (external as { toJSON(): unknown }).toJSON();
|
|
458
|
+
}
|
|
459
|
+
if (external !== null && typeof external === "object" && (external as Record<string, unknown>).Ref === "GCP::ProjectId") {
|
|
460
|
+
return env.GCP_PROJECT_ID || undefined;
|
|
461
|
+
}
|
|
462
|
+
if (typeof external !== "string" || external === "") return undefined;
|
|
463
|
+
return external.startsWith("projects/") ? external.slice("projects/".length).split("/")[0] : external;
|
|
464
|
+
}
|
|
465
|
+
|
|
446
466
|
export function resolveGcpProject(resource: GcpResource, env: NodeJS.ProcessEnv = process.env): string {
|
|
447
|
-
const project =
|
|
467
|
+
const project =
|
|
468
|
+
projectRefProject(resource.spec, env) ||
|
|
469
|
+
env.GOOGLE_CLOUD_PROJECT ||
|
|
470
|
+
resource.metadata?.annotations?.[PROJECT_ID_ANNOTATION];
|
|
448
471
|
if (!project) {
|
|
449
472
|
throw new Error(
|
|
450
|
-
`no GCP project — set GOOGLE_CLOUD_PROJECT or the ${PROJECT_ID_ANNOTATION} annotation`,
|
|
473
|
+
`no GCP project — set spec.projectRef.external, GOOGLE_CLOUD_PROJECT or the ${PROJECT_ID_ANNOTATION} annotation`,
|
|
451
474
|
);
|
|
452
475
|
}
|
|
453
476
|
return project;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The live readers take a resource's project from `projectRef.external`
|
|
3
|
+
* (#4201), the way `CloudRunServiceComposite` declares it, before
|
|
4
|
+
* GOOGLE_CLOUD_PROJECT and the annotations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { afterEach, describe, expect, test } from "vitest";
|
|
8
|
+
import { manifestProjectAnnotations, resolveReadProject } from "./describe-resources";
|
|
9
|
+
|
|
10
|
+
const saved = process.env.GOOGLE_CLOUD_PROJECT;
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
if (saved === undefined) delete process.env.GOOGLE_CLOUD_PROJECT;
|
|
13
|
+
else process.env.GOOGLE_CLOUD_PROJECT = saved;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("resolveReadProject", () => {
|
|
17
|
+
test("reads the entity's projectRef.external with no env or annotation", () => {
|
|
18
|
+
delete process.env.GOOGLE_CLOUD_PROJECT;
|
|
19
|
+
const props = { projectRef: { external: "three-cloud" }, location: "asia-northeast1" };
|
|
20
|
+
expect(resolveReadProject("RunService", "web", { annotations: {} }, new Map(), props)).toBe("three-cloud");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("still names every knob when nothing resolves", () => {
|
|
24
|
+
delete process.env.GOOGLE_CLOUD_PROJECT;
|
|
25
|
+
expect(() => resolveReadProject("RunService", "web", undefined, new Map(), {})).toThrow(/projectRef\.external/);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("manifestProjectAnnotations", () => {
|
|
30
|
+
test("takes a document's spec.projectRef.external", () => {
|
|
31
|
+
const yaml = `apiVersion: run.cnrm.cloud.google.com/v1beta1
|
|
32
|
+
kind: RunService
|
|
33
|
+
metadata:
|
|
34
|
+
name: web
|
|
35
|
+
spec:
|
|
36
|
+
projectRef:
|
|
37
|
+
external: projects/three-cloud
|
|
38
|
+
`;
|
|
39
|
+
expect(manifestProjectAnnotations(yaml).get("RunService/web")).toBe("three-cloud");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GCP pseudo-parameters in spec values are resolved at build, and a build
|
|
3
|
+
* that can't resolve one refuses with the variable named (#4200).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { afterEach, describe, expect, test } from "vitest";
|
|
7
|
+
import { CloudRunServiceComposite } from "./composites/cloud-run-service";
|
|
8
|
+
import { gcpSerializer } from "./serializer";
|
|
9
|
+
|
|
10
|
+
const saved = { project: process.env.GCP_PROJECT_ID, region: process.env.GCP_REGION };
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
for (const [k, v] of [["GCP_PROJECT_ID", saved.project], ["GCP_REGION", saved.region]] as const) {
|
|
13
|
+
if (v === undefined) delete process.env[k];
|
|
14
|
+
else process.env[k] = v;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
function build(): string {
|
|
19
|
+
const { service } = CloudRunServiceComposite({ name: "web", image: "traefik/whoami:v1.10", port: 80 });
|
|
20
|
+
return gcpSerializer.serialize(new Map([["web", service]])) as string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("gcp pseudo-parameters in spec values", () => {
|
|
24
|
+
test("resolve from GCP_PROJECT_ID and GCP_REGION", () => {
|
|
25
|
+
process.env.GCP_PROJECT_ID = "three-cloud";
|
|
26
|
+
process.env.GCP_REGION = "asia-northeast1";
|
|
27
|
+
const yaml = build();
|
|
28
|
+
expect(yaml).toContain("location: asia-northeast1");
|
|
29
|
+
expect(yaml).toContain("external: three-cloud");
|
|
30
|
+
expect(yaml).not.toMatch(/Ref: GCP::/);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("refuse the build, naming each unset variable", () => {
|
|
34
|
+
delete process.env.GCP_PROJECT_ID;
|
|
35
|
+
delete process.env.GCP_REGION;
|
|
36
|
+
expect(build).toThrow(/GCP_REGION, GCP_PROJECT_ID are not set[\s\S]*web: GCP::Region needs GCP_REGION[\s\S]*web: GCP::ProjectId needs GCP_PROJECT_ID/);
|
|
37
|
+
});
|
|
38
|
+
});
|
package/src/serializer.ts
CHANGED
|
@@ -162,6 +162,7 @@ export const gcpSerializer: Serializer = {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
const documents: string[] = [];
|
|
165
|
+
const unresolved: UnresolvedPseudo[] = [];
|
|
165
166
|
|
|
166
167
|
for (const [name, entity] of entities) {
|
|
167
168
|
if (isPropertyDeclarable(entity)) continue;
|
|
@@ -171,9 +172,10 @@ export const gcpSerializer: Serializer = {
|
|
|
171
172
|
const gvk = resolveGVK(entityType);
|
|
172
173
|
if (!gvk) continue;
|
|
173
174
|
|
|
174
|
-
const props =
|
|
175
|
-
isResourceDeclarable(entity) ? entity.props : undefined,
|
|
176
|
-
|
|
175
|
+
const props = resolvePseudoParameters(
|
|
176
|
+
toYAMLValue(isResourceDeclarable(entity) ? entity.props : undefined, entityNames),
|
|
177
|
+
name,
|
|
178
|
+
unresolved,
|
|
177
179
|
) as Record<string, unknown> | undefined;
|
|
178
180
|
|
|
179
181
|
if (!props) continue;
|
|
@@ -223,6 +225,8 @@ export const gcpSerializer: Serializer = {
|
|
|
223
225
|
documents.push(yamlDoc);
|
|
224
226
|
}
|
|
225
227
|
|
|
228
|
+
if (unresolved.length > 0) throw new Error(unresolvedMessage(unresolved));
|
|
229
|
+
|
|
226
230
|
const primary = documents.join("\n---\n");
|
|
227
231
|
const warnings = unwritableOutputWarnings(outputs);
|
|
228
232
|
return warnings.length > 0 ? { primary, warnings } : primary;
|
|
@@ -240,6 +244,42 @@ const PSEUDO_ENV_MAP: Record<string, { envVar: string; fallback: string }> = {
|
|
|
240
244
|
"GCP::Zone": { envVar: "GCP_ZONE", fallback: "us-central1-a" },
|
|
241
245
|
};
|
|
242
246
|
|
|
247
|
+
interface UnresolvedPseudo {
|
|
248
|
+
entity: string;
|
|
249
|
+
ref: string;
|
|
250
|
+
envVar: string;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Replace each GCP pseudo-parameter (`{ Ref: "GCP::Region" }`) in a
|
|
255
|
+
* serialized resource with its environment variable's value (#4200).
|
|
256
|
+
* Config Connector has no parameters, so a `Ref` left in the YAML reaches
|
|
257
|
+
* the API as an object. A variable that isn't set is recorded, and the
|
|
258
|
+
* build refuses with every one named.
|
|
259
|
+
*/
|
|
260
|
+
function resolvePseudoParameters(value: unknown, entity: string, unresolved: UnresolvedPseudo[]): unknown {
|
|
261
|
+
if (Array.isArray(value)) return value.map((v) => resolvePseudoParameters(v, entity, unresolved));
|
|
262
|
+
if (value === null || typeof value !== "object") return value;
|
|
263
|
+
const obj = value as Record<string, unknown>;
|
|
264
|
+
const keys = Object.keys(obj);
|
|
265
|
+
if (keys.length === 1 && keys[0] === "Ref" && typeof obj.Ref === "string" && obj.Ref in PSEUDO_ENV_MAP) {
|
|
266
|
+
const { envVar } = PSEUDO_ENV_MAP[obj.Ref];
|
|
267
|
+
const resolved = process.env[envVar];
|
|
268
|
+
if (resolved) return resolved;
|
|
269
|
+
unresolved.push({ entity, ref: obj.Ref, envVar });
|
|
270
|
+
return value;
|
|
271
|
+
}
|
|
272
|
+
const out: Record<string, unknown> = {};
|
|
273
|
+
for (const [k, v] of Object.entries(obj)) out[k] = resolvePseudoParameters(v, entity, unresolved);
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function unresolvedMessage(unresolved: UnresolvedPseudo[]): string {
|
|
278
|
+
const vars = [...new Set(unresolved.map((u) => u.envVar))];
|
|
279
|
+
const lines = unresolved.map((u) => ` ${u.entity}: ${u.ref} needs ${u.envVar}`);
|
|
280
|
+
return `gcp: ${vars.join(", ")} ${vars.length === 1 ? "is" : "are"} not set, and Config Connector YAML can't carry a pseudo-parameter. Set ${vars.length === 1 ? "it" : "them"} at build, or pass the value explicitly:\n${lines.join("\n")}`;
|
|
281
|
+
}
|
|
282
|
+
|
|
243
283
|
/**
|
|
244
284
|
* Resolve an annotation value to a plain string.
|
|
245
285
|
* PseudoParameter intrinsics are resolved from environment variables;
|