@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.
@@ -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: `GOOGLE_CLOUD_PROJECT` / the entity's own
86
- * annotation (via `resolveGcpProject`, the applier's rule), then the built
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;;;;;GAKG;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,GACpC,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"}
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: `GOOGLE_CLOUD_PROJECT` / the entity's own
103
- * annotation (via `resolveGcpProject`, the applier's rule), then the built
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) };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "257df817d4b1ad04f71ff75c28b578dcff2a2921fe07100da54974937b645941",
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": "2947c3fa4c9b3e3407d761cb6302036cbdc49736886f5bb16407aac326ff42d9"
43
+ "composite": "42adf7f5bc414f125aa92b289f431803d8c659a76e1d3ba8ad393da238c2ac53"
44
44
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gcp",
3
- "version": "0.124.33",
3
+ "version": "0.124.34",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "GCP",
6
6
  "intrinsics": [],
@@ -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 = env.GOOGLE_CLOUD_PROJECT || resource.metadata?.annotations?.[PROJECT_ID_ANNOTATION];
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";
@@ -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,UA6F3B,CAAC"}
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"}
@@ -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.33",
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.33"
79
+ "@intentius/chant": "^0.124.34"
80
80
  }
81
81
  }
@@ -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: `GOOGLE_CLOUD_PROJECT` / the entity's own
123
- * annotation (via `resolveGcpProject`, the applier's rule), then the built
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 = env.GOOGLE_CLOUD_PROJECT || resource.metadata?.annotations?.[PROJECT_ID_ANNOTATION];
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;
@@ -34,6 +34,7 @@ export {
34
34
  isChantOwned,
35
35
  resolveGcpEndpoint,
36
36
  resolveGcpProject,
37
+ projectRefProject,
37
38
  parseManifest,
38
39
  } from "./gcp-apply";
39
40
  export type {
@@ -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 = toYAMLValue(
175
- isResourceDeclarable(entity) ? entity.props : undefined,
176
- entityNames,
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;