@causa/workspace-google 1.3.1 → 1.4.0-beta.2

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.
Files changed (98) hide show
  1. package/README.md +23 -0
  2. package/dist/functions/event-topic/create-backfill-source-bigquery.call.js +2 -2
  3. package/dist/functions/event-topic/query-events-bigquery.call.js +2 -2
  4. package/dist/functions/google-app-check/generate-token.js +3 -1
  5. package/dist/functions/google-firebase-storage/merge-rules.js +3 -1
  6. package/dist/functions/google-firestore/generate-typescript-decorators.js +2 -1
  7. package/dist/functions/google-firestore/merge-rules.js +3 -1
  8. package/dist/functions/google-identity-platform/generate-custom-token.js +7 -2
  9. package/dist/functions/google-pubsub/index.d.ts +1 -1
  10. package/dist/functions/google-pubsub/index.js +1 -1
  11. package/dist/functions/google-pubsub/write-topics.d.ts +7 -0
  12. package/dist/functions/google-pubsub/write-topics.js +17 -3
  13. package/dist/functions/google-services/enable.js +3 -1
  14. package/dist/functions/google-spanner/generate-typescript-decorators.js +2 -1
  15. package/dist/functions/google-spanner/list-databases.d.ts +1 -1
  16. package/dist/functions/google-spanner/write-databases.js +7 -2
  17. package/dist/functions/graph/fetch-environment-metric-series.call.d.ts +3 -0
  18. package/dist/functions/graph/fetch-environment-metric-series.call.js +107 -0
  19. package/dist/functions/graph/fetch-environment-metric-series.d.ts +23 -0
  20. package/dist/functions/graph/fetch-environment-metric-series.js +40 -0
  21. package/dist/functions/graph/get-environment-provider.d.ts +11 -0
  22. package/dist/functions/graph/get-environment-provider.js +20 -0
  23. package/dist/functions/graph/index.d.ts +3 -0
  24. package/dist/functions/graph/index.js +3 -0
  25. package/dist/functions/graph/list-rules.d.ts +11 -0
  26. package/dist/functions/graph/list-rules.js +16 -0
  27. package/dist/functions/index.js +2 -1
  28. package/dist/graph/cloud-run.d.ts +98 -0
  29. package/dist/graph/cloud-run.js +102 -0
  30. package/dist/graph/environment/fetchers/cloud-monitoring-alerts.d.ts +6 -0
  31. package/dist/graph/environment/fetchers/cloud-monitoring-alerts.js +106 -0
  32. package/dist/graph/environment/fetchers/cloud-monitoring.d.ts +5 -0
  33. package/dist/graph/environment/fetchers/cloud-monitoring.js +13 -0
  34. package/dist/graph/environment/fetchers/cloud-run.d.ts +5 -0
  35. package/dist/graph/environment/fetchers/cloud-run.js +88 -0
  36. package/dist/graph/environment/fetchers/cloud-scheduler.d.ts +5 -0
  37. package/dist/graph/environment/fetchers/cloud-scheduler.js +95 -0
  38. package/dist/graph/environment/fetchers/console-links.d.ts +14 -0
  39. package/dist/graph/environment/fetchers/console-links.js +132 -0
  40. package/dist/graph/environment/fetchers/error-reporting.d.ts +5 -0
  41. package/dist/graph/environment/fetchers/error-reporting.js +98 -0
  42. package/dist/graph/environment/fetchers/index.d.ts +5 -0
  43. package/dist/graph/environment/fetchers/index.js +17 -0
  44. package/dist/graph/environment/index.d.ts +9 -0
  45. package/dist/graph/environment/index.js +9 -0
  46. package/dist/graph/environment/load-balancer-backends.d.ts +82 -0
  47. package/dist/graph/environment/load-balancer-backends.js +126 -0
  48. package/dist/graph/environment/monitoring-alerts.d.ts +60 -0
  49. package/dist/graph/environment/monitoring-alerts.js +67 -0
  50. package/dist/graph/environment/monitoring-catalog.d.ts +95 -0
  51. package/dist/graph/environment/monitoring-catalog.js +356 -0
  52. package/dist/graph/environment/monitoring-mappings.d.ts +133 -0
  53. package/dist/graph/environment/monitoring-mappings.js +97 -0
  54. package/dist/graph/environment/monitoring-query.d.ts +116 -0
  55. package/dist/graph/environment/monitoring-query.js +314 -0
  56. package/dist/graph/environment/monitoring-values.d.ts +41 -0
  57. package/dist/graph/environment/monitoring-values.js +119 -0
  58. package/dist/graph/environment/resource-resolvers.d.ts +7 -0
  59. package/dist/graph/environment/resource-resolvers.js +57 -0
  60. package/dist/graph/environment/resources.d.ts +45 -0
  61. package/dist/graph/environment/resources.js +49 -0
  62. package/dist/graph/ids.d.ts +35 -0
  63. package/dist/graph/ids.js +44 -0
  64. package/dist/graph/index.d.ts +7 -0
  65. package/dist/graph/index.js +7 -0
  66. package/dist/graph/rules/configuration/enqueues-assumed-from-google-task-trigger.d.ts +6 -0
  67. package/dist/graph/rules/configuration/enqueues-assumed-from-google-task-trigger.js +39 -0
  68. package/dist/graph/rules/configuration/firestore.d.ts +11 -0
  69. package/dist/graph/rules/configuration/firestore.js +93 -0
  70. package/dist/graph/rules/configuration/index.d.ts +5 -0
  71. package/dist/graph/rules/configuration/index.js +11 -0
  72. package/dist/graph/rules/configuration/service-container.d.ts +13 -0
  73. package/dist/graph/rules/configuration/service-container.js +123 -0
  74. package/dist/graph/rules/terraform/api-router.d.ts +15 -0
  75. package/dist/graph/rules/terraform/api-router.js +117 -0
  76. package/dist/graph/rules/terraform/cloud-run-cron-triggers.d.ts +11 -0
  77. package/dist/graph/rules/terraform/cloud-run-cron-triggers.js +67 -0
  78. package/dist/graph/rules/terraform/cloud-run-grants.d.ts +16 -0
  79. package/dist/graph/rules/terraform/cloud-run-grants.js +118 -0
  80. package/dist/graph/rules/terraform/cloud-run-module.d.ts +6 -0
  81. package/dist/graph/rules/terraform/cloud-run-module.js +29 -0
  82. package/dist/graph/rules/terraform/cloud-run-pubsub-triggers.d.ts +14 -0
  83. package/dist/graph/rules/terraform/cloud-run-pubsub-triggers.js +103 -0
  84. package/dist/graph/rules/terraform/cloud-run-services.d.ts +12 -0
  85. package/dist/graph/rules/terraform/cloud-run-services.js +61 -0
  86. package/dist/graph/rules/terraform/cloud-run-tasks-triggers.d.ts +14 -0
  87. package/dist/graph/rules/terraform/cloud-run-tasks-triggers.js +97 -0
  88. package/dist/graph/rules/terraform/event-topics.d.ts +18 -0
  89. package/dist/graph/rules/terraform/event-topics.js +193 -0
  90. package/dist/graph/rules/terraform/index.d.ts +5 -0
  91. package/dist/graph/rules/terraform/index.js +13 -0
  92. package/dist/graph/rules/terraform/spanner-databases.d.ts +17 -0
  93. package/dist/graph/rules/terraform/spanner-databases.js +180 -0
  94. package/dist/graph/spanner.d.ts +106 -0
  95. package/dist/graph/spanner.js +118 -0
  96. package/dist/graph/terraform-modules.d.ts +87 -0
  97. package/dist/graph/terraform-modules.js +107 -0
  98. package/package.json +30 -29
@@ -0,0 +1,67 @@
1
+ import {} from '@causa/workspace-core';
2
+ import { nodeId, scheduledJobId, triggerId, triggerLocator, } from '@causa/workspace-core/graph';
3
+ import { terraformDeploys } from '@causa/workspace-terraform';
4
+ import { CloudRunFact } from '../../cloud-run.js';
5
+ import { blockResource } from '../../terraform-modules.js';
6
+ /**
7
+ * A `scheduledJob` node per cron trigger of a project, for each Cloud Run module block deploying it with cron triggers
8
+ * enabled. The module names the job `run-<service>-<trigger>`. The locator is the trigger's. The job `realizes` its
9
+ * trigger, and `targets` the service the block deploys.
10
+ *
11
+ * @param graph The context of the extraction.
12
+ * @returns The scheduled jobs, and their edges.
13
+ */
14
+ export async function cloudRunCronTriggers(graph) {
15
+ const { locator } = graph;
16
+ const cloudRun = await graph.get(CloudRunFact);
17
+ const nodes = [];
18
+ const edges = [];
19
+ const warnings = [];
20
+ for (const service of cloudRun) {
21
+ const source = service.block.declaration;
22
+ for (const [name, trigger] of service.cronTriggers) {
23
+ const jobLocator = triggerLocator(service.project.directory, name);
24
+ const job = `run-${service.name}-${name}`;
25
+ nodes.push({
26
+ layer: 'infrastructure',
27
+ type: 'scheduledJob',
28
+ locator: jobLocator,
29
+ name: job,
30
+ sources: [
31
+ source,
32
+ await locator.configurationSource(service.project.context, [
33
+ 'serviceContainer',
34
+ 'triggers',
35
+ name,
36
+ ]),
37
+ ],
38
+ data: {
39
+ resource: await blockResource(graph, service.block, {
40
+ type: 'cloudscheduler.googleapis.com/Job',
41
+ scope: service.project,
42
+ id: [
43
+ 'projects/',
44
+ service.projectPart,
45
+ '/locations/',
46
+ service.locationPart,
47
+ `/jobs/${job}`,
48
+ ],
49
+ }, warnings),
50
+ },
51
+ });
52
+ edges.push(...terraformDeploys(service.block, nodeId('scheduledJob', jobLocator)), {
53
+ type: 'realizes',
54
+ from: scheduledJobId(jobLocator),
55
+ to: triggerId(service.project.directory, name),
56
+ sources: [source],
57
+ }, {
58
+ type: 'targets',
59
+ from: scheduledJobId(jobLocator),
60
+ to: service.id,
61
+ label: trigger.endpoint?.path,
62
+ sources: [source],
63
+ });
64
+ }
65
+ }
66
+ return { nodes, edges, warnings };
67
+ }
@@ -0,0 +1,16 @@
1
+ import { type GraphRuleOutput } from '@causa/workspace-core';
2
+ import { type GraphContext } from '@causa/workspace-core/graph';
3
+ /**
4
+ * The edges granted by the IAM bindings of the Cloud Run module blocks deploying a project.
5
+ *
6
+ * - A `publishes` edge from every service of the project to each broker topic of its `outputs.eventTopics`, when any
7
+ * block grants the publisher role.
8
+ * - An `accesses` edge from every service of the project to each datastore of its outputs, when any block grants
9
+ * access. Spanner access is granted on each database. Firestore access is granted on
10
+ * the whole database, but is declared for the collections listed in the outputs: edges target the collections under
11
+ * each listed root.
12
+ *
13
+ * @param graph The context of the extraction.
14
+ * @returns The edges granted by the blocks.
15
+ */
16
+ export declare function cloudRunGrants(graph: GraphContext): Promise<GraphRuleOutput>;
@@ -0,0 +1,118 @@
1
+ import {} from '@causa/workspace-core';
2
+ import { brokerTopicId, databaseId, databaseLocator, ModelFact, tableId, } from '@causa/workspace-core/graph';
3
+ import { CloudRunFact } from '../../cloud-run.js';
4
+ import { FIRESTORE_ENGINE, firestoreCollectionPath, firestoreDatabaseLocator, SPANNER_ENGINE, } from '../../ids.js';
5
+ /**
6
+ * The edges granted by the IAM bindings of the Cloud Run module blocks deploying a project.
7
+ *
8
+ * - A `publishes` edge from every service of the project to each broker topic of its `outputs.eventTopics`, when any
9
+ * block grants the publisher role.
10
+ * - An `accesses` edge from every service of the project to each datastore of its outputs, when any block grants
11
+ * access. Spanner access is granted on each database. Firestore access is granted on
12
+ * the whole database, but is declared for the collections listed in the outputs: edges target the collections under
13
+ * each listed root.
14
+ *
15
+ * @param graph The context of the extraction.
16
+ * @returns The edges granted by the blocks.
17
+ */
18
+ export async function cloudRunGrants(graph) {
19
+ const { locator, context } = graph;
20
+ const [cloudRun, model] = await Promise.all([
21
+ graph.get(CloudRunFact),
22
+ graph.get(ModelFact),
23
+ ]);
24
+ const edges = [];
25
+ const warnings = [];
26
+ const firestoreDatabase = context
27
+ .asConfiguration()
28
+ .get('google.firestore.database');
29
+ const firestorePaths = [...model.entities.values()].flatMap((e) => {
30
+ const table = e.schema.definition.databases.find((d) => d.engine === FIRESTORE_ENGINE)?.table;
31
+ const path = table ? firestoreCollectionPath(table) : undefined;
32
+ return path ? [path] : [];
33
+ });
34
+ // What the project declares is granted to all its services as soon as one of its blocks grants it.
35
+ for (const [project, services] of Map.groupBy(cloudRun, (s) => s.project)) {
36
+ const configuration = project.context.asConfiguration();
37
+ const publisherBlocks = services
38
+ .filter((s) => s.setPubsubPermissions)
39
+ .map((s) => s.block.declaration);
40
+ if (publisherBlocks.length > 0) {
41
+ const topics = configuration.get('serviceContainer.outputs.eventTopics') ?? [];
42
+ for (const [index, topic] of topics.entries()) {
43
+ const source = await locator.configurationSource(project.context, [
44
+ 'serviceContainer',
45
+ 'outputs',
46
+ 'eventTopics',
47
+ index,
48
+ ]);
49
+ for (const service of services) {
50
+ edges.push({
51
+ type: 'publishes',
52
+ from: service.id,
53
+ to: brokerTopicId(topic),
54
+ sources: [...publisherBlocks, source],
55
+ });
56
+ }
57
+ }
58
+ }
59
+ const outputs = configuration.get('serviceContainer.outputs', {
60
+ unsafe: true,
61
+ });
62
+ const spannerBlocks = services
63
+ .filter((s) => s.setSpannerPermissions)
64
+ .map((s) => s.block.declaration);
65
+ if (spannerBlocks.length > 0) {
66
+ const databases = (outputs?.[SPANNER_ENGINE] ?? []);
67
+ for (const [index, database] of databases.entries()) {
68
+ const source = await locator.configurationSource(project.context, [
69
+ 'serviceContainer',
70
+ 'outputs',
71
+ SPANNER_ENGINE,
72
+ index,
73
+ ]);
74
+ for (const service of services) {
75
+ edges.push({
76
+ type: 'accesses',
77
+ from: service.id,
78
+ to: databaseId(databaseLocator(SPANNER_ENGINE, database)),
79
+ sources: [...spannerBlocks, source],
80
+ });
81
+ }
82
+ }
83
+ }
84
+ const firestoreBlocks = services
85
+ .filter((s) => s.setFirestorePermissions)
86
+ .map((s) => s.block.declaration);
87
+ if (firestoreBlocks.length === 0 || !firestoreDatabase) {
88
+ continue;
89
+ }
90
+ const collections = (outputs?.[FIRESTORE_ENGINE] ?? []);
91
+ for (const [index, collection] of collections.entries()) {
92
+ const source = await locator.configurationSource(project.context, [
93
+ 'serviceContainer',
94
+ 'outputs',
95
+ FIRESTORE_ENGINE,
96
+ index,
97
+ ]);
98
+ const paths = new Set(firestorePaths.filter((p) => p.split('/')[0] === collection));
99
+ if (paths.size === 0) {
100
+ warnings.push({
101
+ message: `Project '${project.name}' is granted Firestore access for '${collection}' but no schema binds to that collection.`,
102
+ sources: [source],
103
+ });
104
+ }
105
+ for (const path of paths) {
106
+ for (const service of services) {
107
+ edges.push({
108
+ type: 'accesses',
109
+ from: service.id,
110
+ to: tableId(firestoreDatabaseLocator(firestoreDatabase), path),
111
+ sources: [...firestoreBlocks, source],
112
+ });
113
+ }
114
+ }
115
+ }
116
+ }
117
+ return { edges, warnings };
118
+ }
@@ -0,0 +1,6 @@
1
+ import { type GraphRule } from '@causa/workspace-core';
2
+ /**
3
+ * The resources created by the blocks of the Cloud Run module, each part following a file of the module: the service,
4
+ * the Pub/Sub, tasks, and cron triggers, and the IAM grants.
5
+ */
6
+ export declare const cloudRunModule: GraphRule;
@@ -0,0 +1,29 @@
1
+ import { GraphOriginKind, } from '@causa/workspace-core';
2
+ import { cloudRunCronTriggers } from './cloud-run-cron-triggers.js';
3
+ import { cloudRunGrants } from './cloud-run-grants.js';
4
+ import { cloudRunPubSubTriggers } from './cloud-run-pubsub-triggers.js';
5
+ import { cloudRunServices } from './cloud-run-services.js';
6
+ import { cloudRunTasksTriggers } from './cloud-run-tasks-triggers.js';
7
+ /**
8
+ * The resources created by the blocks of the Cloud Run module, each part following a file of the module: the service,
9
+ * the Pub/Sub, tasks, and cron triggers, and the IAM grants.
10
+ */
11
+ export const cloudRunModule = {
12
+ name: 'cloudRunModule',
13
+ kind: GraphOriginKind.Declared,
14
+ description: 'The resources each Cloud Run module block creates: the `service` realizing the project read back from `configuration_file`, a push `brokerSubscription` per Pub/Sub trigger, a `queue` per task trigger, and a `scheduledJob` per cron trigger, with the edges between them, and the `publishes`, `accesses`, and `enqueues` edges its IAM bindings grant. Each resource is linked by a `deploys` edge from the projects applying the block.',
15
+ async run(graph) {
16
+ const outputs = await Promise.all([
17
+ cloudRunServices(graph),
18
+ cloudRunPubSubTriggers(graph),
19
+ cloudRunTasksTriggers(graph),
20
+ cloudRunCronTriggers(graph),
21
+ cloudRunGrants(graph),
22
+ ]);
23
+ return {
24
+ nodes: outputs.flatMap((o) => o.nodes ?? []),
25
+ edges: outputs.flatMap((o) => o.edges ?? []),
26
+ warnings: outputs.flatMap((o) => o.warnings ?? []),
27
+ };
28
+ },
29
+ };
@@ -0,0 +1,14 @@
1
+ import { type GraphRuleOutput } from '@causa/workspace-core';
2
+ import { type GraphContext } from '@causa/workspace-core/graph';
3
+ /**
4
+ * A push `brokerSubscription` per Pub/Sub trigger of a project, for each Cloud Run module block deploying it with
5
+ * Pub/Sub triggers enabled. The locator is the trigger's. The module names the subscription `run-<service>-<trigger>`.
6
+ *
7
+ * Each subscription `realizes` its trigger, `targets` the service its module block deploys, and is delivered to by the
8
+ * broker topic of its trigger. A topic that no event schema of the workspace defines is created outside of it, and
9
+ * gets its own `brokerTopic` node.
10
+ *
11
+ * @param graph The context of the extraction.
12
+ * @returns The subscriptions, the external broker topics, and their edges.
13
+ */
14
+ export declare function cloudRunPubSubTriggers(graph: GraphContext): Promise<GraphRuleOutput>;
@@ -0,0 +1,103 @@
1
+ import {} from '@causa/workspace-core';
2
+ import { brokerSubscriptionId, brokerTopicId, ModelFact, nodeId, triggerId, triggerLocator, } from '@causa/workspace-core/graph';
3
+ import { terraformDeploys } from '@causa/workspace-terraform';
4
+ import { CloudRunFact } from '../../cloud-run.js';
5
+ import { blockResource } from '../../terraform-modules.js';
6
+ /**
7
+ * A push `brokerSubscription` per Pub/Sub trigger of a project, for each Cloud Run module block deploying it with
8
+ * Pub/Sub triggers enabled. The locator is the trigger's. The module names the subscription `run-<service>-<trigger>`.
9
+ *
10
+ * Each subscription `realizes` its trigger, `targets` the service its module block deploys, and is delivered to by the
11
+ * broker topic of its trigger. A topic that no event schema of the workspace defines is created outside of it, and
12
+ * gets its own `brokerTopic` node.
13
+ *
14
+ * @param graph The context of the extraction.
15
+ * @returns The subscriptions, the external broker topics, and their edges.
16
+ */
17
+ export async function cloudRunPubSubTriggers(graph) {
18
+ const { locator } = graph;
19
+ const [cloudRun, model] = await Promise.all([
20
+ graph.get(CloudRunFact),
21
+ graph.get(ModelFact),
22
+ ]);
23
+ const nodes = [];
24
+ const edges = [];
25
+ const warnings = [];
26
+ const subscriptions = new Set();
27
+ for (const service of cloudRun) {
28
+ const source = service.block.declaration;
29
+ for (const [name, trigger] of service.pubsubTriggers) {
30
+ const subscriptionLocator = triggerLocator(service.project.directory, name);
31
+ const subscriptionId = brokerSubscriptionId(subscriptionLocator);
32
+ if (subscriptions.has(subscriptionLocator)) {
33
+ warnings.push({
34
+ message: `Trigger '${name}' of '${service.project.name}' is deployed with Pub/Sub triggers by several module blocks. A single subscription node stands for several subscriptions.`,
35
+ sources: [source],
36
+ });
37
+ }
38
+ subscriptions.add(subscriptionLocator);
39
+ const filter = trigger['google.pubSub']?.filter;
40
+ const subscription = `run-${service.name}-${name}`;
41
+ const data = {
42
+ filter: typeof filter === 'string' ? filter : undefined,
43
+ resource: await blockResource(graph, service.block, {
44
+ type: 'pubsub.googleapis.com/Subscription',
45
+ scope: service.project,
46
+ id: [
47
+ 'projects/',
48
+ service.projectPart,
49
+ `/subscriptions/${subscription}`,
50
+ ],
51
+ }, warnings),
52
+ };
53
+ nodes.push({
54
+ layer: 'infrastructure',
55
+ type: 'brokerSubscription',
56
+ locator: subscriptionLocator,
57
+ name: subscription,
58
+ sources: [
59
+ source,
60
+ await locator.configurationSource(service.project.context, [
61
+ 'serviceContainer',
62
+ 'triggers',
63
+ name,
64
+ ]),
65
+ ],
66
+ data,
67
+ });
68
+ edges.push(...terraformDeploys(service.block, nodeId('brokerSubscription', subscriptionLocator)), {
69
+ type: 'realizes',
70
+ from: subscriptionId,
71
+ to: triggerId(service.project.directory, name),
72
+ sources: [source],
73
+ }, {
74
+ type: 'targets',
75
+ from: subscriptionId,
76
+ to: service.id,
77
+ label: trigger.endpoint?.path,
78
+ sources: [source],
79
+ });
80
+ if (typeof trigger.topic !== 'string') {
81
+ continue;
82
+ }
83
+ const topicSource = await locator.configurationSource(service.project.context, ['serviceContainer', 'triggers', name, 'topic']);
84
+ edges.push({
85
+ type: 'delivers',
86
+ from: brokerTopicId(trigger.topic),
87
+ to: subscriptionId,
88
+ sources: [source, topicSource],
89
+ });
90
+ if (!model.topics.has(trigger.topic)) {
91
+ nodes.push({
92
+ layer: 'infrastructure',
93
+ type: 'brokerTopic',
94
+ locator: trigger.topic,
95
+ name: trigger.topic,
96
+ description: 'A topic no event schema of the workspace defines, created outside of it.',
97
+ sources: [topicSource],
98
+ });
99
+ }
100
+ }
101
+ }
102
+ return { nodes, edges, warnings };
103
+ }
@@ -0,0 +1,12 @@
1
+ import { type GraphRuleOutput } from '@causa/workspace-core';
2
+ import { type GraphContext } from '@causa/workspace-core/graph';
3
+ /**
4
+ * A `service` node per block of the Cloud Run module, and a `realizes` edge from it to the project whose configuration
5
+ * file the block reads. The service name is the block's `name` argument or the project name, and `platform` is the
6
+ * project's `serviceContainer.platform`. Blocks whose project cannot be found, and arguments that cannot be evaluated,
7
+ * are reported.
8
+ *
9
+ * @param graph The context of the extraction.
10
+ * @returns The services, and their edges.
11
+ */
12
+ export declare function cloudRunServices(graph: GraphContext): Promise<GraphRuleOutput>;
@@ -0,0 +1,61 @@
1
+ import {} from '@causa/workspace-core';
2
+ import { projectId, serviceLocator, } from '@causa/workspace-core/graph';
3
+ import { terraformDeploys } from '@causa/workspace-terraform';
4
+ import { CloudRunFact } from '../../cloud-run.js';
5
+ import { blockResource } from '../../terraform-modules.js';
6
+ /**
7
+ * A `service` node per block of the Cloud Run module, and a `realizes` edge from it to the project whose configuration
8
+ * file the block reads. The service name is the block's `name` argument or the project name, and `platform` is the
9
+ * project's `serviceContainer.platform`. Blocks whose project cannot be found, and arguments that cannot be evaluated,
10
+ * are reported.
11
+ *
12
+ * @param graph The context of the extraction.
13
+ * @returns The services, and their edges.
14
+ */
15
+ export async function cloudRunServices(graph) {
16
+ const { locator } = graph;
17
+ const cloudRun = await graph.get(CloudRunFact);
18
+ const nodes = [];
19
+ const edges = [];
20
+ const warnings = [];
21
+ for (const service of cloudRun) {
22
+ const source = service.block.declaration;
23
+ const data = {
24
+ platform: service.project.context
25
+ .asConfiguration()
26
+ .get('serviceContainer.platform'),
27
+ resource: await blockResource(graph, service.block, {
28
+ type: 'run.googleapis.com/Service',
29
+ scope: service.project,
30
+ id: [
31
+ 'projects/',
32
+ service.projectPart,
33
+ '/locations/',
34
+ service.locationPart,
35
+ `/services/${service.name}`,
36
+ ],
37
+ }, warnings),
38
+ };
39
+ nodes.push({
40
+ layer: 'infrastructure',
41
+ type: 'service',
42
+ locator: serviceLocator(service.project.directory, service.name),
43
+ name: service.name,
44
+ sources: [
45
+ source,
46
+ await locator.configurationSource(service.project.context, [
47
+ 'project',
48
+ 'name',
49
+ ]),
50
+ ],
51
+ data,
52
+ });
53
+ edges.push(...terraformDeploys(service.block, service.id), {
54
+ type: 'realizes',
55
+ from: service.id,
56
+ to: projectId(service.project.directory),
57
+ sources: [source],
58
+ });
59
+ }
60
+ return { nodes, edges, warnings };
61
+ }
@@ -0,0 +1,14 @@
1
+ import { type GraphRuleOutput } from '@causa/workspace-core';
2
+ import { type GraphContext } from '@causa/workspace-core/graph';
3
+ /**
4
+ * The resources a Cloud Run module block creates for the task triggers of a project, when tasks triggers are enabled:
5
+ *
6
+ * - A `queue` node per `queue` of the task triggers. The module suffixes the queue name with a random string, such that
7
+ * only a prefix of the resource name is known. The locator is the declared name. The queue `realizes` the task
8
+ * triggers declaring it, and `targets` the service the block deploys, which is the HTTP target of the tasks.
9
+ * - An `enqueues` edge from every service of the project to each queue.
10
+ *
11
+ * @param graph The context of the extraction.
12
+ * @returns The queues, and their edges.
13
+ */
14
+ export declare function cloudRunTasksTriggers(graph: GraphContext): Promise<GraphRuleOutput>;
@@ -0,0 +1,97 @@
1
+ import {} from '@causa/workspace-core';
2
+ import { nodeId, queueId, triggerId, } from '@causa/workspace-core/graph';
3
+ import { terraformDeploys } from '@causa/workspace-terraform';
4
+ import { CloudRunFact } from '../../cloud-run.js';
5
+ import { blockResource } from '../../terraform-modules.js';
6
+ /**
7
+ * The resources a Cloud Run module block creates for the task triggers of a project, when tasks triggers are enabled:
8
+ *
9
+ * - A `queue` node per `queue` of the task triggers. The module suffixes the queue name with a random string, such that
10
+ * only a prefix of the resource name is known. The locator is the declared name. The queue `realizes` the task
11
+ * triggers declaring it, and `targets` the service the block deploys, which is the HTTP target of the tasks.
12
+ * - An `enqueues` edge from every service of the project to each queue.
13
+ *
14
+ * @param graph The context of the extraction.
15
+ * @returns The queues, and their edges.
16
+ */
17
+ export async function cloudRunTasksTriggers(graph) {
18
+ const { locator } = graph;
19
+ const cloudRun = await graph.get(CloudRunFact);
20
+ const nodes = [];
21
+ const edges = [];
22
+ const warnings = [];
23
+ for (const service of cloudRun) {
24
+ const source = service.block.declaration;
25
+ for (const [name, trigger] of service.tasksTriggers) {
26
+ const queueSource = await locator.configurationSource(service.project.context, ['serviceContainer', 'triggers', name, 'queue']);
27
+ if (typeof trigger.queue !== 'string') {
28
+ warnings.push({
29
+ message: `Task trigger '${name}' has no queue.`,
30
+ sources: [queueSource],
31
+ });
32
+ continue;
33
+ }
34
+ const resource = await blockResource(graph, service.block, {
35
+ type: 'cloudtasks.googleapis.com/Queue',
36
+ scope: service.project,
37
+ prefix: true,
38
+ id: [
39
+ 'projects/',
40
+ service.projectPart,
41
+ '/locations/',
42
+ service.locationPart,
43
+ `/queues/${trigger.queue}-`,
44
+ ],
45
+ }, warnings);
46
+ nodes.push({
47
+ layer: 'infrastructure',
48
+ type: 'queue',
49
+ locator: trigger.queue,
50
+ name: trigger.queue,
51
+ sources: [source, queueSource],
52
+ data: { resource },
53
+ });
54
+ edges.push(...terraformDeploys(service.block, nodeId('queue', trigger.queue)), {
55
+ type: 'realizes',
56
+ from: queueId(trigger.queue),
57
+ to: triggerId(service.project.directory, name),
58
+ sources: [source],
59
+ }, {
60
+ type: 'targets',
61
+ from: queueId(trigger.queue),
62
+ to: service.id,
63
+ label: trigger.endpoint?.path,
64
+ sources: [source],
65
+ });
66
+ }
67
+ }
68
+ for (const services of Map.groupBy(cloudRun, (s) => s.project).values()) {
69
+ for (const granting of services.filter((s) => s.setTasksPermissions)) {
70
+ const queues = new Map();
71
+ for (const [name, trigger] of granting.tasksTriggers) {
72
+ if (typeof trigger.queue === 'string' && !queues.has(trigger.queue)) {
73
+ queues.set(trigger.queue, name);
74
+ }
75
+ }
76
+ for (const [queue, trigger] of queues) {
77
+ for (const service of services) {
78
+ edges.push({
79
+ type: 'enqueues',
80
+ from: service.id,
81
+ to: queueId(queue),
82
+ sources: [
83
+ granting.block.declaration,
84
+ await locator.configurationSource(granting.project.context, [
85
+ 'serviceContainer',
86
+ 'triggers',
87
+ trigger,
88
+ 'queue',
89
+ ]),
90
+ ],
91
+ });
92
+ }
93
+ }
94
+ }
95
+ }
96
+ return { nodes, edges, warnings };
97
+ }
@@ -0,0 +1,18 @@
1
+ import { type GraphRule } from '@causa/workspace-core';
2
+ /**
3
+ * The source of the Causa Terraform module creating the Pub/Sub topics, and the raw events BigQuery tables.
4
+ */
5
+ export declare const EVENT_TOPICS_MODULE_SOURCE = "causa-io/event-topics-pubsub/google";
6
+ /**
7
+ * The resources created by the event topics module block.
8
+ *
9
+ * - A `brokerTopic` node per event topic, named by the topic ID: the module creates one Pub/Sub topic per topic listed
10
+ * by `EventTopicList`. It `realizes` the event topic of the same ID.
11
+ * - When the block has a raw events dataset (`bigquery_raw_events_dataset`, or
12
+ * `google.pubSub.bigQueryStorage.rawEventsDatasetId`), a `database` node for the BigQuery dataset, and for each
13
+ * topic:
14
+ * - A `table` node, named by the topic ID with `.` and `-` replaced by `_`.
15
+ * - A BigQuery `brokerSubscription` node: the module creates one `bq-<topic>` subscription per topic, writing events
16
+ * to the topic's raw table. The broker topic `delivers` to it, and it `targets` the table.
17
+ */
18
+ export declare const eventTopicsModule: GraphRule;